package seedu.manager.logic.commands;

import java.util.HashMap;
import java.util.Optional;

import seedu.manager.commons.core.EventsCenter;
import seedu.manager.commons.core.Messages;
import seedu.manager.commons.core.UnmodifiableObservableList;
import seedu.manager.commons.events.ui.JumpToTaskListRequestEvent;
import seedu.manager.commons.exceptions.IllegalValueException;
import seedu.manager.model.task.ReadOnlyTask;
import seedu.manager.model.task.Task;
import seedu.manager.model.task.UniqueTaskList;
import seedu.manager.model.task.Task.TaskProperties;
import seedu.manager.model.task.UniqueTaskList.TaskNotFoundException;

/**
 * Allows tasks to be edited. Uses an index to extract the task to be edited and changes its
 * properties according to the new properties given
 * @author varungupta
 *
 */
public class EditCommand extends Command implements UndoableCommand {
    
    public static final String COMMAND_WORD = "edit";

    public static final String MESSAGE_USAGE = COMMAND_WORD
            + ": Edits the task identified by the index number used in the last task listing.\n"
            + "Parameters: INDEX (must be a positive integer) [DESC] [<extensions>]\n"
            + "Example: " + COMMAND_WORD + " 1 Dinner with Guinevere venue Under the Stars priority high";

    public static final String MESSAGE_SUCCESS = "Edited Task: %1$s";
    public static final String MESSAGE_DUPLICATE_PARAMS = "The new parameters are the same as before";
    public static final String UNDO_SUCCESS = "Undone the previous edit: %1$s";

    public final int targetIndex;
    
    private final HashMap<TaskProperties, Optional<String>> editedProperties;

    public EditCommand(int targetIndex, HashMap<TaskProperties, Optional<String>> editedProperties) 
            throws IllegalValueException {
        this.targetIndex = targetIndex;
        this.editedProperties = editedProperties;
    }

    public Task newTask;
    public Task oldTask;

    @Override
    public CommandResult execute() {
        assert model != null;
        
        UnmodifiableObservableList<ReadOnlyTask> lastShownList = model.getSortedFilteredTaskList();

        if (lastShownList.size() < targetIndex) {
            indicateAttemptToExecuteIncorrectCommand();
            return new CommandResult(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
        }

        ReadOnlyTask taskToEdit = lastShownList.get(targetIndex - 1);
        
        try {
        	HashMap<TaskProperties, Optional<String>> newProperties = 
        		buildNewPropsFromOldAndEdited(taskToEdit.getPropertiesAsStrings(), editedProperties);
        	
            newTask = new Task(newProperties);
            oldTask = new Task(taskToEdit);
            
            model.addTask(newTask);
            model.deleteTask(taskToEdit);
            jumpToTask(newTask);
            
            this.addUndo(this);
            
            return new CommandResult(String.format(MESSAGE_SUCCESS, newTask.getAsPrettyText()));
        } catch (TaskNotFoundException e) {
            return new CommandResult("The target task cannot be missing");
        } catch (UniqueTaskList.DuplicateTaskException e) {
            return new CommandResult(MESSAGE_DUPLICATE_PARAMS);
        } catch (IllegalValueException e) {
			return new CommandResult(e.getMessage());
		}
    }
    
    /**
     * Builds a HashMap of new properties using old properties of task and new properties entered
     * by user
     * 
     * @param oldProperties
     * @param editedProperties
     */
    private HashMap<TaskProperties, Optional<String>> buildNewPropsFromOldAndEdited(
            HashMap<TaskProperties, Optional<String>> oldProperties, 
            HashMap<TaskProperties, Optional<String>> editedProperties
            ) {
        HashMap<TaskProperties, Optional<String>> newProperties = new HashMap<>();
        
        for (TaskProperties prop : TaskProperties.values()) {
            if (editedProperties.get(prop).isPresent()) {
                newProperties.put(prop, editedProperties.get(prop));
            } else {
                newProperties.put(prop, oldProperties.get(prop));
            }
        }
        
        return newProperties;
    }
    
    @Override
    public CommandResult undoIt() {
    	assert model != null;
    	
    	try {
    		model.addTask(oldTask);
    		model.deleteTask(newTask);
    		jumpToTask(oldTask);
    		
            return new CommandResult(String.format(UNDO_SUCCESS, oldTask));
        } catch (TaskNotFoundException e) {
            return new CommandResult("The target task cannot be missing");
        } catch (UniqueTaskList.DuplicateTaskException e) {
            return new CommandResult(MESSAGE_DUPLICATE_PARAMS);
        }
    	
    }
    
}

@@ -482,34 +482,117 @@
 .model.task.
-UniqueTask
+Tag;%0Aimport seedu.manager.model.task.UniqueTaskList;%0Aimport seedu.manager.model.tag.UniqueTag
 List;%0Aimport
@@ -2893,41 +2893,461 @@
     
-jumpToTask(newTask);%0A            
+%0A            if(newTask.getTag().isPresent()) %7B%0A            model.addTag((Tag) newTask.getTag().get());%0A            %7D%0A            if(taskToEdit.getTag().isPresent()) %7B%0A                model.deleteTag((Tag) taskToEdit.getTag().get());%0A            %7D%0A            %0A            int newIndex = model.getIndexOfTask(newTask);%0A            assert newIndex != -1;%0A            %0A            EventsCenter.getInstance().post(new JumpToTaskListRequestEvent(newIndex));
 %0A   
@@ -4873,35 +4873,8 @@
 k);%0A
-    %09%09jumpToTask(oldTask);%0A
     

Tag list can work in edit command.