package seedu.task.ui;

import com.google.common.eventbus.Subscribe;

import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import seedu.task.commons.core.LogsCenter;
import seedu.task.commons.events.ui.IncorrectCommandAttemptedEvent;
import seedu.task.commons.events.ui.SwitchCommandBoxFunctionEvent;
import seedu.task.commons.util.FxViewUtil;
import seedu.task.logic.Logic;
import seedu.task.logic.commands.*;

import java.util.logging.Logger;

public class CommandBox extends UiPart {
    private final Logger logger = LogsCenter.getLogger(CommandBox.class);
    private static final String FXML = "CommandBox.fxml";
    
    private final String TEXT_LIVE_SEARCH = "Enter your search term here...";
    private final String TEXT_COMMAND_BOX = "Enter command here...";

    private AnchorPane placeHolderPane;
    private AnchorPane commandPane;
    private ResultDisplay resultDisplay;
    String previousCommandTest;

    private Logic logic;

    @FXML
    private TextField commandTextField;
    private CommandResult mostRecentResult;
    private EventHandler<KeyEvent> liveSearchHandler;
    private boolean isSearchMode;

    public static CommandBox load(Stage primaryStage, AnchorPane commandBoxPlaceholder,
            ResultDisplay resultDisplay, Logic logic) {
        CommandBox commandBox = UiPartLoader.loadUiPart(primaryStage, commandBoxPlaceholder, new CommandBox());
        commandBox.configure(resultDisplay, logic);
        commandBox.addToPlaceholder();
        return commandBox;
    }

    public void configure(ResultDisplay resultDisplay, Logic logic) {
        this.resultDisplay = resultDisplay;
        this.logic = logic;
        this.liveSearchHandler = new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                logic.updateTaskListFilter(commandTextField.getText());
            }
        };
        this.isSearchMode = false;
        
        registerAsAnEventHandler(this);
    }

    private void addToPlaceholder() {
        SplitPane.setResizableWithParent(placeHolderPane, false);
        placeHolderPane.getChildren().add(commandTextField);
        FxViewUtil.applyAnchorBoundaryParameters(commandPane, 0.0, 0.0, 0.0, 0.0);
        FxViewUtil.applyAnchorBoundaryParameters(commandTextField, 0.0, 0.0, 0.0, 0.0);
    }

    @Override
    public void setNode(Node node) {
        commandPane = (AnchorPane) node;
    }

    @Override
    public String getFxmlPath() {
        return FXML;
    }

    @Override
    public void setPlaceholder(AnchorPane pane) {
        this.placeHolderPane = pane;
    }


    @FXML
    private void handleCommandInputChanged() {
        //@@author A0141052Y
        if (isSearchMode) {
            // Will always set back on enter and ensure that command is not executed!
            setToCommandBox();
            commandTextField.setText("");
        //@@author
        } else {
            //Take a copy of the command text
            previousCommandTest = commandTextField.getText();

            /* We assume the command is correct. If it is incorrect, the command box will be changed accordingly
             * in the event handling code {@link #handleIncorrectCommandAttempted}
             */
            setStyleToIndicateCorrectCommand();
            mostRecentResult = logic.execute(previousCommandTest);
            resultDisplay.postMessage(mostRecentResult.feedbackToUser);
            logger.info("Result: " + mostRecentResult.feedbackToUser);
        }
    }


    /**
     * Sets the command box style to indicate a correct command.
     */
    private void setStyleToIndicateCorrectCommand() {
        commandTextField.getStyleClass().remove("error");
        commandTextField.setText("");
    }

    @Subscribe
    private void handleIncorrectCommandAttempted(IncorrectCommandAttemptedEvent event){
        logger.info(LogsCenter.getEventHandlingLogMessage(event,"Invalid command: " + previousCommandTest));
        setStyleToIndicateIncorrectCommand();
        restoreCommandText();
    }
    
    //@@author A0141052Y
    @Subscribe
    private void handleSwitchCommandBoxFunction(SwitchCommandBoxFunctionEvent event) {
        setToLiveSearch();
    }
    
    private void setToLiveSearch() {
        commandTextField.setPromptText(TEXT_LIVE_SEARCH);
        this.isSearchMode = true;
        commandTextField.addEventHandler(KeyEvent.KEY_TYPED, this.liveSearchHandler);
    }
    
    private void setToCommandBox() {
        commandTextField.setPromptText(TEXT_COMMAND_BOX);
        this.isSearchMode = false;
        commandTextField.removeEventHandler(KeyEvent.KEY_TYPED, this.liveSearchHandler);
    }

    //@@author
    /**
     * Restores the command box text to the previously entered command
     */
    private void restoreCommandText() {
        commandTextField.setText(previousCommandTest);
    }

    /**
     * Sets the command box style to indicate an error
     */
    private void setStyleToIndicateIncorrectCommand() {
        commandTextField.getStyleClass().add("error");
    }

}

@@ -63,16 +63,101 @@
 cribe;%0A%0A
+import javafx.beans.value.ChangeListener;%0Aimport javafx.beans.value.ObservableValue;%0A
 import j
@@ -1344,37 +1344,37 @@
 private 
-EventHandler%3CKeyEvent
+ChangeListener%3CString
 %3E liveSe
@@ -1985,33 +1985,32 @@
 new 
-EventHandler%3CKeyEvent
+ChangeListener%3CString
 %3E()
- 
 %7B%0A  
@@ -2057,29 +2057,94 @@
 oid 
+c
 han
-dle(KeyEvent event
+ged(ObservableValue%3C? extends String%3E observable, String oldValue, String newValue
 ) %7B%0A
@@ -2190,34 +2190,16 @@
 ter(
-commandTextField.getText()
+newValue
 );%0A 
@@ -4706,49 +4706,35 @@
 eld.
-addEventHandler(KeyEvent.KEY_TYPED, this.
+textProperty().addListener(
 live
@@ -4919,52 +4919,38 @@
 eld.
-removeEventHandler(KeyEvent.KEY_TYPED, this.
+textProperty().removeListener(
 live

Change CommandBox event listener to listen to textual changes, not keypresses