package jfdi.logic.interfaces;

import com.google.common.eventbus.EventBus;
import jfdi.common.utilities.JfdiLogger;
import jfdi.parser.InputParser;
import jfdi.storage.apis.AliasDb;
import jfdi.storage.apis.MainStorage;
import jfdi.storage.apis.TaskDb;
import jfdi.ui.UI;

import java.util.Optional;
import java.util.Stack;
import java.util.logging.Logger;

/**
 * @author Liu Xinan
 */
public abstract class Command {

    protected static final Logger logger = JfdiLogger.getLogger();
    protected static final EventBus eventBus = UI.getEventBus();

    protected static final Stack<Command> undoStack = new Stack<>();
    protected static final Stack<Command> redoStack = new Stack<>();

    protected static InputParser parser = InputParser.getInstance();
    protected static MainStorage mainStorage = MainStorage.getInstance();
    protected static TaskDb taskDb = TaskDb.getInstance();
    protected static AliasDb aliasDb = AliasDb.getInstance();

    private static boolean redoing = false;
    private static Optional<String> lastSuggestion = Optional.empty();

    /**
     * Executes the command.
     */
    public abstract void execute();

    /**
     * Undoes the command.
     */
    public abstract void undo();

    protected static void setRedoing(boolean redo) {
        redoing = redo;
    }

    public static void setLastSuggestion(Optional<String> suggestion) {
        lastSuggestion = suggestion;
    }

    public static Optional<String> getLastSuggestion() {
        return lastSuggestion;
    }

    protected void pushToUndoStack() {
        if (!redoing) {
            while (!redoStack.empty()) {
                undoStack.push(redoStack.pop());
            }
        }

        undoStack.push(this);
    }

    protected void pushToRedoStack() {
        redoStack.push(this);
    }

    //================================================================
    // List of setters for testing.
    //================================================================


    public static void setParser(InputParser parser) {
        Command.parser = parser;
    }

    public static void setMainStorage(MainStorage mainStorage) {
        Command.mainStorage = mainStorage;
    }

    public static void setTaskDb(TaskDb taskDb) {
        Command.taskDb = taskDb;
    }

    public static void setAliasDb(AliasDb aliasDb) {
        Command.aliasDb = aliasDb;
    }
}

@@ -1906,16 +1906,28 @@
 setters 
+and getters 
 for test
@@ -2397,11 +2397,547 @@
 b;%0A    %7D
+%0A%0A    public static Stack%3CCommand%3E getUndoStack() %7B%0A        return undoStack;%0A    %7D%0A%0A    public static Stack%3CCommand%3E getRedoStack() %7B%0A        return redoStack;%0A    %7D%0A%0A    public static InputParser getParser() %7B%0A        return parser;%0A    %7D%0A%0A    public static MainStorage getMainStorage() %7B%0A        return mainStorage;%0A    %7D%0A%0A    public static TaskDb getTaskDb() %7B%0A        return taskDb;%0A    %7D%0A%0A    public static AliasDb getAliasDb() %7B%0A        return aliasDb;%0A    %7D%0A%0A    public static boolean isRedoing() %7B%0A        return redoing;%0A    %7D
 %0A%7D%0A

Add getters to `Command` for testing