package com.google.sps.data;

import com.google.cloud.Date;
import java.lang.StringBuilder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream; 

/** Class containing Event object setters for variables that user can change about event */
public final class Event {
  private final String eventId;
  private String name;
  private String description;
  private String location;
  private Date date;
  private String time;
  private Set<String> labels;
  private Set<VolunteeringOpportunity> opportunities;
  private Set<User> attendees;
  private User host;

  @Override
  public String toString() {
    StringBuilder str = new StringBuilder();
    str.append("Event Info: \n");
    str.append("ID: " + eventId + "\n");
    str.append("Host: " + host.toString() + "\n");
    str.append("Name: " + name + "\n");
    str.append("Description: " + description + "\n");
    str.append("Location: " + location + "\n");
    str.append("Date: " + date.toString() + "\n");
    str.append("Time: " + time + "\n");
    str.append("Labels: " + labels.toString() + "\n");
    str.append("Volunteer Opportunities: ");
    for (VolunteeringOpportunity opportunity : this.opportunities) {
      str.append(opportunity.toString() + "\n");
    }
    str.append("Attendees: ");
    for (User attendee : this.attendees) {
      str.append(attendee.toString() + "\n");
    }
    return str.toString();
  }

  public static class Builder {
    // Required parameters
    private String name;
    private String description;
    private Set<String> labels;
    private String location;
    private Date date;
    private String time;
    private User host;

    // Optional parameters
    private String eventId = UUID.randomUUID().toString();
    private Set<VolunteeringOpportunity> opportunities = new HashSet<>();
    private Set<User> attendees = new HashSet<>();

    public Builder(
        String name,
        String description,
        Set<String> labels,
        String location,
        Date date,
        String time,
        User host) {
      this.name = name;
      this.description = description;
      this.labels = labels;
      this.location = location;
      this.date = date;
      this.time = time;
      this.host = host;
    }

    public Builder setId(String eventId) {
      this.eventId = eventId;
      return this;
    }

    public Builder setName(String name) {
      this.name = name;
      return this;
    }

    public Builder setDescription(String description) {
      this.description = description;
      return this;
    }

    public Builder setLabels(Set<String> labels) {
      this.labels = labels;
      return this;
    }

    public Builder setLocation(String location) {
      this.location = location;
      return this;
    }

    public Builder setDate(Date date) {
      this.date = date;
      return this;
    }

    public Builder setTime(String time) {
      this.time = time;
      return this;
    }

    public Builder setHost(User host) {
      this.host = host;
      return this;
    }

    public Builder setOpportunities(Set<VolunteeringOpportunity> opportunities) {
      this.opportunities = opportunities;
      return this;
    }

    public Builder addOpportunity(VolunteeringOpportunity opportunity) {
      this.opportunities.add(opportunity);
      return this;
    }

    public Builder removeOpportunity(VolunteeringOpportunity opportunity) {
      this.opportunities.remove(opportunity);
      return this;
    }

    public Builder setAttendees(Set<User> attendees) {
      this.attendees = attendees;
      return this;
    }

    public Builder addAttendee(User attendee) {
      this.attendees.add(attendee);
      return this;
    }

    public Builder removeAttendee(User attendee) {
      this.attendees.remove(attendee);
      return this;
    }

    public Event build() {
      return new Event(this);
    }

    public Builder mergeFrom(Event other) {
      this.name = other.getName();
      this.description = other.getDescription();
      this.labels = other.getLabels();
      this.location = other.getLocation();
      this.date = other.getDate();
      this.time = other.getTime();
      this.host = other.getHost();

      if (!other.getOpportunities().isEmpty()) {
        this.opportunities = other.getOpportunities();
      }
      if (!other.getAttendees().isEmpty()) {
        this.attendees = other.getAttendees();
      }
      if (!other.getImageUrl().isEmpty()) {
        this.imageUrl = other.getImageUrl();
      }
      return this;
    }
  }

  private Event(Builder builder) {
    this.eventId = builder.eventId;
    this.name = builder.name;
    this.description = builder.description;
    this.labels = builder.labels;
    this.location = builder.location;
    this.date = builder.date;
    this.time = builder.time;
    this.opportunities = builder.opportunities;
    this.attendees = builder.attendees;
    this.host = builder.host;
    this.imageUrl = builder.imageUrl;
  }

  public String getId() {
    return this.eventId;
  }

  public String getName() {
    return this.name;
  }

  public String getDescription() {
    return this.description;
  }

  public Set<String> getLabels() {
    return this.labels;
  }

  public void setLabel(String newLabel) {
    this.labels.add(newLabel);
  }

  public void removeLabel(String deletedLabel) {
    this.labels.remove(deletedLabel);
  }

  public String getLocation() {
    return this.location;
  }

  public Date getDate() {
    return this.date;
  }

  public String getTime() {
    return this.time;
  }

  public Set<VolunteeringOpportunity> getOpportunities() {
    return this.opportunities;
  }

  public Set<String> getOpportunitiesIds() {
    return opportunities.stream()
        .map(VolunteeringOpportunity::getOpportunityId)
        .collect(Collectors.toSet());
  }

  public Set<User> getAttendees() {
    return this.attendees;
  }

  public Set<String> getAttendeeIds() {
    return attendees.stream().map(User::getEmail).collect(Collectors.toSet());
  }

  public User getHost() {
    return this.host;
  }

  public Builder toBuilder() {
    return new Builder(
        this.name, this.description, this.labels, this.location, this.date, this.time, this.host)
        .mergeFrom(this);
  }
}

@@ -763,24 +763,51 @@
 e User host;
+%0A  private String imageUrl;
 %0A%0A  @Overrid
@@ -1587,24 +1587,73 @@
 %5Cn%22);%0A    %7D%0A
+    str.append(%22Image URL: %22 + imageUrl + %22%5Cn%22);%0A
     return s
@@ -2131,16 +2131,50 @@
 Set%3C%3E();
+%0A    private String imageUrl = %22%22;
 %0A%0A    pu
@@ -4120,32 +4120,140 @@
 rn this;%0A    %7D%0A%0A
+    public Builder setImageUrl(String imageUrl) %7B%0A      this.imageUrl = imageUrl;%0A      return this;%0A    %7D%0A%0A
     public Event
@@ -6465,24 +6465,24 @@
 getHost() %7B%0A
-
     return t
@@ -6492,24 +6492,87 @@
 .host;%0A  %7D%0A%0A
+  public String getImageUrl() %7B%0A    return this.imageUrl;%0A  %7D%0A%0A
   public Bui

Add imageUrl to Event.java