package jfdi.logic.commands;

import jfdi.logic.events.AddTaskDoneEvent;
import jfdi.logic.events.AddTaskFailEvent;
import jfdi.logic.interfaces.Command;
import jfdi.storage.data.TaskAttributes;
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;

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

    private String description;
    private LocalDateTime startDateTime;
    private LocalDateTime endDateTime;
    private Duration[] reminders;
    private String[] tags;

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

    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 addTag(String tag) {
            this.tags.add(tag);
            return this;
        }

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

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

    }

    @Override
    public void execute() {
        TaskAttributes task = new TaskAttributes();
        task.setDescription(description);
        task.setStartDateTime(startDateTime);
        task.setEndDateTime(endDateTime);
        task.setReminders(reminders);
        task.setTags(tags);
        try {
            task.save();
            eventBus.post(new AddTaskDoneEvent(task));
        } catch (InvalidTaskParametersException e) {
            eventBus.post(new AddTaskFailEvent(AddTaskFailEvent.Error.EMPTY_DESCRIPTION));
        } catch (NoAttributesChangedException e) {
            // Should not happen for creating tasks
            e.printStackTrace();
        } catch (InvalidIdException e) {
            // Should not happen for creating tasks
            e.printStackTrace();
        }
    }
}

@@ -479,16 +479,43 @@
 lection;
+%0Aimport java.util.Optional;
 %0A%0A/**%0A *
@@ -620,32 +620,41 @@
 on;%0A    private 
+Optional%3C
 LocalDateTime st
@@ -642,32 +642,33 @@
 al%3CLocalDateTime
+%3E
  startDateTime;%0A
@@ -679,16 +679,25 @@
 private 
+Optional%3C
 LocalDat
@@ -693,32 +693,33 @@
 al%3CLocalDateTime
+%3E
  endDateTime;%0A  
@@ -893,32 +893,52 @@
 startDateTime = 
+Optional.ofNullable(
 builder.startDat
@@ -934,32 +934,33 @@
 er.startDateTime
+)
 ;%0A        this.e
@@ -972,16 +972,36 @@
 eTime = 
+Optional.ofNullable(
 builder.
@@ -1003,32 +1003,33 @@
 lder.endDateTime
+)
 ;%0A        this.r
@@ -2615,17 +2615,9 @@
     
-task.setS
+s
 tart
@@ -2628,10 +2628,37 @@
 Time
-(s
+.ifPresent(start -%3E task.setS
 tart
@@ -2657,32 +2657,39 @@
 setStartDateTime
+(start)
 );%0A        task.
@@ -2687,17 +2687,9 @@
     
-task.setE
+e
 ndDa
@@ -2698,10 +2698,35 @@
 Time
-(e
+.ifPresent(end -%3E task.setE
 ndDa
@@ -2723,32 +2723,37 @@
 k.setEndDateTime
+(end)
 );%0A        task.

Use `Optionals` for some fields in `AddTaskCommand`