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;
    }
}

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 and getters 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;
    }

    public static Stack<Command> getUndoStack() {
        return undoStack;
    }

    public static Stack<Command> getRedoStack() {
        return redoStack;
    }

    public static InputParser getParser() {
        return parser;
    }

    public static MainStorage getMainStorage() {
        return mainStorage;
    }

    public static TaskDb getTaskDb() {
        return taskDb;
    }

    public static AliasDb getAliasDb() {
        return aliasDb;
    }

    public static boolean isRedoing() {
        return redoing;
    }
}

Add getters to `Command` for testing