package seedu.watodo.logic.commands;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import seedu.watodo.commons.exceptions.IllegalValueException;
import seedu.watodo.logic.commands.exceptions.CommandException;
import seedu.watodo.model.tag.Tag;
import seedu.watodo.model.tag.UniqueTagList;
import seedu.watodo.model.task.DateTime;
import seedu.watodo.model.task.DeadlineTask;
import seedu.watodo.model.task.Description;
import seedu.watodo.model.task.EventTask;
import seedu.watodo.model.task.FloatingTask;
import seedu.watodo.model.task.Task;
import seedu.watodo.model.task.UniqueTaskList;

/**
 * Adds a task to the task manager.
 */
public class AddCommand extends Command {

    public static final String COMMAND_WORD = "add";

    public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to the task manager. "
            + "Parameters: TASK [by/ DATETIME] [from/ START_DATETIME] [to/ END_DATE_TIME] [#TAG]...\n"
            + "Example: " + COMMAND_WORD
            + " read Lord of the rings by/ next thurs #personal";

    public static final String MESSAGE_SUCCESS = "New task added: %1$s";
    public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task manager";

    public enum TaskType { FLOAT, DEADLINE, EVENT, INVALID }
    private Task toAdd;

    /**
     * Creates an AddCommand using raw values
     *
     * @throws IllegalValueException if any of the raw values are invalid
     */
    public AddCommand(String description, boolean hasDeadline, Optional<String> deadline, boolean hasStartDate,
            Optional<String> startDate, boolean hasEndDate, Optional<String> endDate, Set<String> tags)
        throws IllegalValueException {

        assert description != null;

        final Set<Tag> tagSet = new HashSet<>();
        for (String tagName : tags) {
            tagSet.add(new Tag(tagName));
        }

        TaskType taskType = checkTaskType(hasDeadline, hasStartDate, hasEndDate);

        switch (taskType) {
        case FLOAT:
            this.toAdd = new FloatingTask(new Description(description), new UniqueTagList(tagSet));
            break;
        case DEADLINE:
            this.toAdd = new DeadlineTask(new Description(description), new DateTime(deadline.get()),
                    new UniqueTagList(tagSet));
            break;
        case EVENT:
            this.toAdd = new EventTask(new Description(description), new DateTime(startDate.get()),
                    new DateTime(endDate.get()), new UniqueTagList(tagSet));
            break;
        case INVALID:
        default:
            throw new IllegalValueException("Too many/few DATETIME arguments!");
        }
    }

    /**
     * Checks the type of task(floating, deadline or event) to be added
     * based on the DATETIME parameters entered by the user.
     * @throws IllegalValueException if both deadline and startDate are entered,
     * or if only one of startDate or endDate is entered
     */
    private static TaskType checkTaskType(boolean hasDeadline, boolean hasStartDate, boolean hasEndDate)
            throws IllegalValueException {
        if (!hasDeadline && !hasStartDate && !hasEndDate) {
            return TaskType.FLOAT;
        }
        if (hasDeadline && !hasStartDate && !hasEndDate) {
            return TaskType.DEADLINE;
        }
        if (!hasDeadline && hasStartDate && hasEndDate) {
            return TaskType.EVENT;
        }
        return TaskType.INVALID;
    }


    @Override
    public CommandResult execute() throws CommandException {
        assert model != null;
        try {
            model.addTask(toAdd);
            return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
        } catch (UniqueTaskList.DuplicateTaskException e) {
            throw new CommandException(MESSAGE_DUPLICATE_TASK);
        }

    }

}

@@ -391,149 +391,17 @@
 k.De
-adlineTask;%0Aimport seedu.watodo.model.task.Description;%0Aimport seedu.watodo.model.task.EventTask;%0Aimport seedu.watodo.model.task.FloatingTask
+scription
 ;%0Aim
@@ -1787,41 +1787,25 @@
     
-TaskType taskType = checkTaskType
+if(isFloatingTask
 (has
@@ -1843,58 +1843,11 @@
 ate)
-;%0A%0A        switch (taskType) %7B%0A        case FLOAT:
+) %7B
 %0A   
@@ -1872,24 +1872,16 @@
 d = new 
-Floating
 Task(new
@@ -1947,41 +1947,77 @@
     
-    break;%0A        case DEADLINE:
+%7D%0A        if(isDeadlineTask(hasDeadline, hasStartDate, hasEndDate)) %7B
 %0A   
@@ -2042,24 +2042,16 @@
 d = new 
-Deadline
 Task(new
@@ -2106,36 +2106,16 @@
 .get()),
-%0A                   
  new Uni
@@ -2147,38 +2147,74 @@
     
-    break;%0A        case EVENT:
+%7D%0A        if(isEventTask(hasDeadline, hasStartDate, hasEndDate)) %7B
 %0A   
@@ -2239,21 +2239,16 @@
 d = new 
-Event
 Task(new
@@ -2325,16 +2325,30 @@
         
+              
 new Date
@@ -2408,62 +2408,10 @@
     
-    break;%0A        case INVALID:%0A        default:%0A    
+%7D%0A
     
@@ -2483,26 +2483,16 @@
 nts!%22);%0A
-        %7D%0A
     %7D%0A%0A 
@@ -2773,24 +2773,25 @@
 red%0A     */%0A
+%0A
     private 
@@ -2794,37 +2794,30 @@
 ate 
-static 
+boolean isFloating
 Task
-Type checkTaskType
 (boo
@@ -2875,16 +2875,17 @@
 EndDate)
+%7B
 %0A       
@@ -2889,55 +2889,15 @@
     
-    throws IllegalValueException %7B%0A        if (
+return 
 !has
@@ -2940,69 +2940,59 @@
 Date
-) %7B
+;
 %0A    
+%7D%0A
     
-    return TaskType.FLOAT;%0A        %7D%0A        if (
+private boolean isDeadlineTask(boolean 
 hasD
@@ -2990,37 +2990,42 @@
 lean hasDeadline
- && !
+, boolean 
 hasStartDate && 
@@ -3012,37 +3012,42 @@
 ean hasStartDate
- && !
+, boolean 
 hasEndDate) %7B%0A  
@@ -3033,33 +3033,32 @@
 lean hasEndDate)
- 
 %7B%0A            re
@@ -3055,61 +3055,106 @@
     
-    
 return 
-TaskType.DEADLINE;%0A        %7D%0A        if (!
+hasDeadline && !hasStartDate && !hasEndDate;%0A    %7D%0A    private boolean isEventTask(boolean 
 hasD
@@ -3160,19 +3160,25 @@
 Deadline
- &&
+, boolean
  hasStar
@@ -3182,19 +3182,25 @@
 tartDate
- &&
+, boolean
  hasEndD
@@ -3203,23 +3203,18 @@
 EndDate)
- 
 %7B%0A
-    
         
@@ -3224,65 +3224,50 @@
 urn 
-TaskType.EVENT;%0A        %7D%0A        return TaskType.INVALID
+!hasDeadline && hasStartDate && hasEndDate
 ;%0A  

refactor add command