//@@author A0138493W
package utask.logic.commands;

import java.util.List;

import utask.commons.core.Messages;
import utask.logic.commands.exceptions.CommandException;
import utask.logic.commands.inteface.ReversibleCommand;
import utask.model.task.ReadOnlyTask;
import utask.model.task.Task;
import utask.model.task.UniqueTaskList.TaskNotFoundException;
import utask.ui.helper.DelayedExecution;

/**
 * Deletes a task identified using it's last displayed index from the uTask.
 */
public class DeleteCommand extends Command implements ReversibleCommand {

    public static final String COMMAND_WORD = "delete";
    public static final String COMMAND_FORMAT = "INDEX (must be a positive integer)";

    public static final String MESSAGE_USAGE = COMMAND_WORD
            + ": Deletes the task identified by the index number used in the last task listing.\n"
            + "Parameters: " + COMMAND_FORMAT + "\n"
            + "Example: " + COMMAND_WORD + " 1";

    public static final String MESSAGE_DELETE_TASK_SUCCESS = "Tasks have been deleted";

    ReadOnlyTask taskToDelete;
    public final List<Integer> targetList;


    public DeleteCommand(List<Integer> targetList) {
        this.targetList = targetList;
    }

    @Override
    public CommandResult execute() throws CommandException {

        for (int targetIndex : targetList) {
            checkIfGivenIndexIsValid(targetIndex);
            taskToDelete = getTaskToDelete(targetIndex);

            //Do selection effect for 1 task only. It will cause race condition when doing multiple effect in a loop
            if (targetList.size() == 1) {
                notifyUI(taskToDelete);
                new DelayedExecution((e)-> {
                    deleteTask(taskToDelete);
                }).run();
            } else {
                deleteTask(taskToDelete);
            }
        }

        return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS));
    }

    private void checkIfGivenIndexIsValid(int targetIndex) throws CommandException {
        if (model.getTotalSizeOfLists() < targetIndex) {
            throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
        }
    }

    private void deleteTask(ReadOnlyTask taskToDelete) {
        try {
            model.deleteTask(taskToDelete);
            model.addUndoCommand(this);
        } catch (TaskNotFoundException pnfe) {
            assert false : "The target task cannot be missing";
        }
    }

    private ReadOnlyTask getTaskToDelete(int targetIndex) {
        //- 1 as helper method is using zero-based indexing
        List<ReadOnlyTask> list = model.getUnderlyingListByIndex(targetIndex - 1);

        int actualInt = model.getActualIndexFromDisplayIndex(targetIndex - 1);
        return list.get(actualInt);
    }

    @Override
    public void undo() throws Exception {
        model.addTask((Task) taskToDelete);
        notifyUI(taskToDelete);
    }

    @Override
    public void redo() throws Exception {
        notifyUI(taskToDelete);

        //Access to deleteTask() must be delayed to prevent race condition with notifyUI
        new DelayedExecution((e)-> {
            try {
                model.deleteTask(taskToDelete);
            } catch (TaskNotFoundException pnfe) {
                //This exception is handled as it is not possible to hit this exception with normal usage
                assert false : "The target task cannot be missing";
            }
        }).run();
    }

}

@@ -45,16 +45,75 @@
 mands;%0A%0A
+import java.util.Collections;%0Aimport java.util.LinkedList;%0A
 import j
@@ -127,16 +127,16 @@
 l.List;%0A
-
 %0Aimport 
@@ -1134,16 +1134,52 @@
 Delete;%0A
+    List%3CReadOnlyTask%3E deleteTasks;%0A
     publ
@@ -1306,16 +1306,70 @@
 etList;%0A
+        deleteTasks = new LinkedList%3CReadOnlyTask%3E();%0A
     %7D%0A%0A 
@@ -1595,16 +1595,59 @@
 tIndex);
+%0A            deleteTasks.add(taskToDelete);
 %0A%0A      
@@ -2040,24 +2040,61 @@
 %0A        %7D%0A%0A
+        model.addUndoCommand(this);%0A%0A
         retu
@@ -2531,48 +2531,8 @@
 e);%0A
-            model.addUndoCommand(this);%0A
     
@@ -3049,43 +3049,214 @@
     
-model.addTask((Task) taskToDelete);
+Collections.reverse(deleteTasks); //Ensures that items are restored in previous state.%0A        for (int i = 0; i %3C deleteTasks.size(); i++) %7B%0A            model.addTask((Task) deleteTasks.get(i));%0A        %7D%0A
 %0A   
@@ -3371,33 +3371,127 @@
 (taskToDelete);%0A
+        Collections.reverse(deleteTasks); //Ensures that items are restored in previous state.
 %0A
-
         //Access
@@ -3610,32 +3610,99 @@
           try %7B%0A
+                for (int i = 0; i %3C deleteTasks.size(); i++) %7B%0A    
                 
@@ -3714,38 +3714,69 @@
 .deleteTask(
-taskToD
+(Task) d
 elete
-);
+Tasks.get(i));%0A                %7D
 %0A           

Add logic to restore mutliple deletes