package seedu.watodo.logic.commands;

import seedu.watodo.commons.core.Messages;
import seedu.watodo.commons.core.UnmodifiableObservableList;
import seedu.watodo.logic.commands.exceptions.CommandException;
import seedu.watodo.model.task.ReadOnlyTask;
import seedu.watodo.model.task.Task;
import seedu.watodo.model.task.TaskStatus;
import seedu.watodo.model.task.UniqueTaskList;
import seedu.watodo.model.task.UniqueTaskList.DuplicateTaskException;

//@@author A0141077L
/**
 * Marks a task identified using it's last displayed index from the task manager
 * as completed.
 */
public class MarkCommand extends Command {

    public static final String COMMAND_WORD = "mark";

    public static final String MESSAGE_USAGE = COMMAND_WORD + ": Sets the status of the task identified to done "
            + "by the index number used in the last task listing as completed.\n"
            + "Parameters: INDEX (must be a positive integer) [MORE_INDICES]\n" + "Example: " + COMMAND_WORD
            + " 1 2";

    public static final String MESSAGE_MARK_TASK_SUCCESS = "Task completed: %1$s";
    public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task manager.";
    public static final String MESSAGE_STATUS_DONE = "The task status is already set to Done.";

    private int[] filteredTaskListIndices;
    private int undoMarkInt;
    private Task undoMark;
    private Task markedTask;

    public MarkCommand(int[] args) {
        this.filteredTaskListIndices = args;

        for (int i = 0; i < filteredTaskListIndices.length; i++) {
            assert filteredTaskListIndices != null;
            assert filteredTaskListIndices.length > 0;
            assert filteredTaskListIndices[i] > 0;

            // converts filteredTaskListIndex to from one-based to zero-based.
            filteredTaskListIndices[i] = filteredTaskListIndices[i] - 1;
        }
    }

    @Override
    public CommandResult execute() throws CommandException {
        final StringBuilder tasksMarkedMessage = new StringBuilder();

        for (int i = 0; i < filteredTaskListIndices.length; i++) {
            UnmodifiableObservableList<ReadOnlyTask> lastShownList = model.getFilteredTaskList();

            if (filteredTaskListIndices[i] >= lastShownList.size()) {
                throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
            }

            ReadOnlyTask taskToMark = lastShownList.get(filteredTaskListIndices[i]);
            this.undoMark = new Task(taskToMark);

            try {
                markedTask = createMarkedTask(taskToMark);
                model.updateTask(filteredTaskListIndices[i], markedTask);
                this.undoMarkInt = filteredTaskListIndices[i];

            } catch (UniqueTaskList.DuplicateTaskException dpe) {
                throw new CommandException(MESSAGE_DUPLICATE_TASK);
            }

            tasksMarkedMessage.append(String.format(MESSAGE_MARK_TASK_SUCCESS, taskToMark) + "\n");
        }

        return new CommandResult(tasksMarkedMessage.toString());
    }

    //@@author A0139845R

    @Override
    public void unexecute() {
        try {
            model.updateFilteredListToShowAll();
            model.updateTask(undoMarkInt, undoMark);
        } catch (DuplicateTaskException e) {

        }
    }

    @Override
    public void redo() {
        try {
            model.updateFilteredListToShowAll();
            this.execute();
        } catch (CommandException e) {
        }
    }

    //@@author

    /**
     * Creates and returns a {@code Task} with the details of {@code taskToMark}
     */
    private static Task createMarkedTask(ReadOnlyTask taskToMark) throws CommandException {
        assert taskToMark != null;

        if (taskToMark.getStatus() == TaskStatus.DONE) {
            throw new CommandException(MESSAGE_STATUS_DONE);
        }

        Task markedTask = new Task(taskToMark.getDescription(), taskToMark.getStartDate(), taskToMark.getEndDate(),
                taskToMark.getTags());
        markedTask.setStatus(TaskStatus.DONE);

        return markedTask;
    }

}

@@ -31,16 +31,41 @@
 mands;%0A%0A
+import java.util.Stack;%0A%0A
 import s
@@ -752,16 +752,28 @@
 AND_WORD
+%0A           
  + %22: Se
@@ -994,16 +994,28 @@
 ample: %22
+%0A           
  + COMMA
@@ -1385,19 +1385,32 @@
 private 
-int
+Stack%3C Integer %3E
  undoMar
@@ -1426,21 +1426,30 @@
  private
+ Stack%3C
  Task
+ %3E
  undoMar
@@ -1564,16 +1564,103 @@
  args;%0A%0A
+        undoMark = new Stack%3C Task %3E();%0A        undoMarkInt = new Stack%3C Integer %3E();%0A%0A
         
@@ -2640,27 +2640,30 @@
 his.undoMark
- = 
+.push(
 new Task(tas
@@ -2670,17 +2670,19 @@
 kToMark)
-;
+);%0A
 %0A%0A      
@@ -2858,19 +2858,22 @@
 oMarkInt
- = 
+.push(
 filtered
@@ -2890,16 +2890,17 @@
 dices%5Bi%5D
+)
 ;%0A%0A     
@@ -3351,32 +3351,78 @@
 istToShowAll();%0A
+            while (!undoMark.isEmpty()) %7B%0A    
             mode
@@ -3445,16 +3445,22 @@
 oMarkInt
+.pop()
 , undoMa
@@ -3457,26 +3457,46 @@
 (), undoMark
-);
+.pop());%0A            %7D
 %0A        %7D c

Fix undo and redo for mark task to support multiple marks