//@@author A0147984L
package seedu.address.logic.commands;

import java.util.List;

import seedu.address.commons.core.Messages;
import seedu.address.commons.exceptions.IllegalValueException;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.task.Event;
import seedu.address.model.task.ReadOnlyRecurringTask;
import seedu.address.model.task.ReadOnlyTask;
import seedu.address.model.task.ReadOnlyTask.RecurringProperty;
import seedu.address.model.task.RecurringEvent;
import seedu.address.model.task.RecurringTask;
import seedu.address.model.task.Task;
import seedu.address.model.task.UniqueTaskList.DuplicateTaskException;
import seedu.address.model.task.UniqueTaskList.TaskNotFoundException;

/**
 * Edits the details of an existing recurring task in Dueue.
 */
public class EditNextCommand extends EditCommand {

  //@@author A0143409J
    private ReadOnlyTask finishedOnceTask;

    /**
     * Create editNext command using an index for specific task and description for the edited task
     */
    public EditNextCommand(int filteredTaskListIndex, EditTaskDescriptor editTaskDescriptor) {
        super(filteredTaskListIndex, editTaskDescriptor);
        finishedOnceTask = null;
    }

    public EditNextCommand(ReadOnlyTask task, Task oldTask, ReadOnlyTask finishedOnceTask) {
        super(task, oldTask);
        this.finishedOnceTask = finishedOnceTask;
    }

    @Override
    public CommandResult execute() throws CommandException {
        List<ReadOnlyTask> lastShownList = model.getFilteredTaskList();

        if (filteredTaskListIndex >= lastShownList.size()) {
            throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
        }

        ReadOnlyTask taskToEdit = lastShownList.get(filteredTaskListIndex);
        if (!(taskToEdit instanceof ReadOnlyRecurringTask)) {
            throw new CommandException("The task to edit once should be a recurring task.");
        }
        ReadOnlyTask editTask = lastShownList.get(filteredTaskListIndex);

        try {
            oldTask = createRecurringTaskOrEvent(editTask);
            Task newTask = createEditedTask(taskToEdit, editTaskDescriptor);
            newTask.setRecurringProperty(RecurringProperty.NON_RECURRING);
            task = createTaskOrEvent(newTask);
            ((ReadOnlyRecurringTask) taskToEdit).finishOnce();
            finishedOnceTask = createRecurringTaskOrEvent(taskToEdit);
            model.updateTask(filteredTaskListIndex, taskToEdit);
            model.addTask((Task) task);
            this.isSuccess = true;
        } catch (IllegalValueException e) {
            throw new CommandException(e.getMessage());
        }

        model.updateFilteredListToShowAllUnfinishedTasks();
        return new CommandResult(CommandFormatter.undoFormatter(
                String.format(MESSAGE_EDIT_TASK_SUCCESS, taskToEdit.getName()), COMMAND_EDIT));
    }

    @Override
    public boolean isUndoable() {
        return true;
    }

    @Override
    public CommandResult undo(String message) throws CommandException {
        assert model != null;
        try {
            if (finishedOnceTask != null) {
                model.deleteTask(task);
                model.addTask(oldTask);
                model.deleteTask(finishedOnceTask);
                Task temp = (Task) task;
                this.task = oldTask;
                this.oldTask = temp;
                this.finishedOnceTask = null;
                this.isSuccess = true;
            } else {
                Task temp = createTaskOrEvent(oldTask);
                model.addTask(oldTask);
                oldTask = createRecurringTaskOrEvent(task);
                ((ReadOnlyRecurringTask) task).finishOnce();
                finishedOnceTask = createRecurringTaskOrEvent(task);
                model.deleteTask(task);
                model.addTask((Task) finishedOnceTask);
                this.task = temp;
                this.isSuccess = true;
            }
        } catch (TaskNotFoundException e) {
            e.printStackTrace();
        } catch (DuplicateTaskException e) {
            e.printStackTrace();
        } catch (IllegalValueException e) {
            e.printStackTrace();
        }
        model.updateFilteredListToShowAllUnfinishedTasks();
        isSuccess = true;
        return new CommandResult(CommandFormatter.undoMessageFormatter(message, getUndoCommandWord()));
    }

    @Override
    public Command getUndoCommand() {
        if (isSuccess) {
            return new EditNextCommand(task, oldTask, finishedOnceTask);
        } else {
            return null;
        }
    }

    private Task createTaskOrEvent(ReadOnlyTask newTask) throws IllegalValueException {
        if (newTask.isEvent()) {
            return new Event(newTask);
        } else {
            return new Task(newTask);
        }
    }

    private Task createRecurringTaskOrEvent(ReadOnlyTask newTask) throws IllegalValueException {
        if (newTask.isEvent()) {
            return new RecurringEvent(newTask);
        } else {
            return new RecurringTask(newTask);
        }
    }
}

@@ -12,13 +12,13 @@
 A014
-7984L
+3409J
 %0Apac
@@ -783,16 +783,21 @@
 ng task 
+once 
 in Dueue
@@ -798,16 +798,237 @@
  Dueue.%0A
+ * Only the next occurrence of the recurring task will be modified.%0A * Effictively, a new typical task is created to replace the next occurrence,%0A * and the due date of the recurring task is pushed until the next period.%0A
  */%0Apubl
@@ -1079,31 +1079,8 @@
  %7B%0A%0A
-  //@@author A0143409J%0A
     
@@ -1227,16 +1227,145 @@
 ed task%0A
+     *%0A     * @param filteredTaskListIndex Index of the task to edit%0A     * @param editTaskDescriptor All the fields for editing%0A
      */%0A
@@ -1553,24 +1553,285 @@
 ull;%0A    %7D%0A%0A
+    /**%0A     * Create editNextCommand for the execution of Redo.%0A     *%0A     * @param task The new task to add%0A     * @param oldTask The formerly finished recurring task%0A     * @param finishedOnceTask The new recurring task which has been finished once%0A     */%0A
     public E
@@ -5219,32 +5219,232 @@
        %7D%0A    %7D%0A%0A
+    /**%0A     * Create a new task or event based on isEvent%0A     *%0A     * @param newTask A typical task or typical event%0A     * @return a new task or event%0A     * @throws IllegalValueException%0A     */%0A
     private Task
@@ -5655,24 +5655,258 @@
    %7D%0A    %7D%0A%0A
+    /**%0A     * Create a new Recurring task or event based on isEvent%0A     *%0A     * @param newTask A recurring task or recurring event%0A     * @return A new recurring task or recurring event%0A     * @throws IllegalValueException%0A     */%0A
     private 

Write javadoc for editNextCommand