package jfdi.logic.commands;

import jfdi.logic.events.AddTaskDoneEvent;
import jfdi.logic.events.AddTaskFailedEvent;
import jfdi.logic.interfaces.Command;
import jfdi.storage.apis.TaskAttributes;
import jfdi.storage.exceptions.DuplicateTaskException;
import jfdi.storage.exceptions.InvalidIdException;
import jfdi.storage.exceptions.InvalidTaskParametersException;
import jfdi.storage.exceptions.NoAttributesChangedException;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;

/**
 * @author Liu Xinan
 */
public class AddTaskCommand extends Command {

    private String description;
    private Optional<LocalDateTime> startDateTime;
    private Optional<LocalDateTime> endDateTime;
    private Duration[] reminders;
    private String[] tags;
    private int id = -1;

    private AddTaskCommand(Builder builder) {
        this.description = builder.description;
        this.startDateTime = Optional.ofNullable(builder.startDateTime);
        this.endDateTime = Optional.ofNullable(builder.endDateTime);
        this.reminders = builder.reminders.toArray(new Duration[0]);
        this.tags = builder.tags.toArray(new String[0]);
    }

    public String getDescription() {
        return description;
    }

    public Optional<LocalDateTime> getStartDateTime() {
        return startDateTime;
    }

    public Optional<LocalDateTime> getEndDateTime() {
        return endDateTime;
    }

    public Duration[] getReminders() {
        return reminders;
    }

    public String[] getTags() {
        return tags;
    }

    public static class Builder {

        String description;
        LocalDateTime startDateTime;
        LocalDateTime endDateTime;
        ArrayList<Duration> reminders = new ArrayList<>();
        ArrayList<String> tags = new ArrayList<>();

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

        public Builder setStartDateTime(LocalDateTime startDateTime) {
            this.startDateTime = startDateTime;
            return this;
        }

        public Builder setEndDateTime(LocalDateTime endDateTime) {
            this.endDateTime = endDateTime;
            return this;
        }

        public Builder addReminder(Duration reminder) {
            this.reminders.add(reminder);
            return this;
        }

        public Builder addReminders(Collection<Duration> reminders) {
            this.reminders.addAll(reminders);
            return this;
        }

        public Builder setReminders(Collection<Duration> reminders) {
            this.reminders = new ArrayList<>(reminders);
            return this;
        }

        public Builder addTag(String tag) {
            this.tags.add(tag);
            return this;
        }

        public Builder addTags(Collection<String> tags) {
            this.tags.addAll(tags);
            return this;
        }

        public Builder setTags(Collection<String> tags) {
            this.tags = new ArrayList<>(tags);
            return this;
        }

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

    }

    @Override
    public void execute() {
        TaskAttributes task = new TaskAttributes();
        task.setDescription(description);
        startDateTime.ifPresent(start -> task.setStartDateTime(start));
        endDateTime.ifPresent(end -> task.setEndDateTime(end));
        try {
            task.save();
            this.id = task.getId();

            pushToUndoStack();
            eventBus.post(new AddTaskDoneEvent(task));
        } catch (InvalidTaskParametersException e) {
            eventBus.post(new AddTaskFailedEvent(
                AddTaskFailedEvent.Error.EMPTY_DESCRIPTION));
        } catch (DuplicateTaskException e) {
            eventBus.post(new AddTaskFailedEvent(
                AddTaskFailedEvent.Error.DUPLICATED_TASK));
        } catch (NoAttributesChangedException e) {
            // Should not happen for creating tasks
            assert false;
        } catch (InvalidIdException e) {
            // Should not happen for creating tasks
            assert false;
        }
    }

    @Override
    public void undo() {
        try {
            taskDb.destroy(id);

            pushToRedoStack();
        } catch (InvalidIdException e) {
            // Should not happen for creating tasks
            assert false;
        }
    }

}

@@ -777,69 +777,8 @@
 me;%0A
-    private Duration%5B%5D reminders;%0A    private String%5B%5D tags;%0A
     
@@ -798,16 +798,16 @@
 d = -1;%0A
+
 %0A    pri
@@ -1039,134 +1039,8 @@
 e);%0A
-        this.reminders = builder.reminders.toArray(new Duration%5B0%5D);%0A        this.tags = builder.tags.toArray(new String%5B0%5D);%0A
     
@@ -1300,140 +1300,8 @@
  %7D%0A%0A
-    public Duration%5B%5D getReminders() %7B%0A        return reminders;%0A    %7D%0A%0A    public String%5B%5D getTags() %7B%0A        return tags;%0A    %7D%0A%0A
     
@@ -1434,119 +1434,8 @@
 ime;
-%0A        ArrayList%3CDuration%3E reminders = new ArrayList%3C%3E();%0A        ArrayList%3CString%3E tags = new ArrayList%3C%3E();
 %0A%0A  
@@ -1878,840 +1878,8 @@
  %7D%0A%0A
-        public Builder addReminder(Duration reminder) %7B%0A            this.reminders.add(reminder);%0A            return this;%0A        %7D%0A%0A        public Builder addReminders(Collection%3CDuration%3E reminders) %7B%0A            this.reminders.addAll(reminders);%0A            return this;%0A        %7D%0A%0A        public Builder setReminders(Collection%3CDuration%3E reminders) %7B%0A            this.reminders = new ArrayList%3C%3E(reminders);%0A            return this;%0A        %7D%0A%0A        public Builder addTag(String tag) %7B%0A            this.tags.add(tag);%0A            return this;%0A        %7D%0A%0A        public Builder addTags(Collection%3CString%3E tags) %7B%0A            this.tags.addAll(tags);%0A            return this;%0A        %7D%0A%0A        public Builder setTags(Collection%3CString%3E tags) %7B%0A            this.tags = new ArrayList%3C%3E(tags);%0A            return this;%0A        %7D%0A%0A
     
@@ -2149,22 +2149,14 @@
 ent(
-start -%3E 
 task
-.
+::
 setS
@@ -2171,15 +2171,8 @@
 Time
-(start)
 );%0A 
@@ -2204,20 +2204,14 @@
 ent(
-end -%3E 
 task
-.
+::
 setE
@@ -2224,13 +2224,8 @@
 Time
-(end)
 );%0A 
@@ -2755,108 +2755,10 @@
 ion 
-e) %7B%0A            // Should not happen for creating tasks%0A            assert false;%0A        %7D catch (
+%7C 
 Inva

Remove unused attributes from `AddTaskCommand`