import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { undoRedoConfig } from '../../types/world/worldConstants';

type UndoRedo2DStore = {
    undoStack: UndoRedo2DTypes[];
    redoStack: UndoRedo2DTypes[];

    push2D: (entry: UndoRedo2DTypes) => void;
    undo2D: () => UndoRedo2DTypes | undefined;
    redo2D: () => UndoRedo2DTypes | undefined;
    clearUndoRedo2D: () => void;

    peekUndo2D: () => UndoRedo2DTypes | undefined;
    peekRedo2D: () => UndoRedo2DTypes | undefined;
};

export const createUndoRedo2DStore = () => {
    return create<UndoRedo2DStore>()(
        immer((set, get) => ({
            undoStack: [],
            redoStack: [],

            push2D: (entry) => {
                set((state) => {
                    state.undoStack.push(entry);

                    if (state.undoStack.length > undoRedoConfig.undoRedoCount) {
                        state.undoStack.shift();
                    }

                    state.redoStack = [];
                });
            },

            undo2D: () => {
                let lastAction: UndoRedo2DTypes | undefined;
                set((state) => {
                    lastAction = state.undoStack.pop();
                    if (lastAction) {
                        state.redoStack.unshift(lastAction);
                    }
                });
                return lastAction;
            },

            redo2D: () => {
                let redoAction: UndoRedo2DTypes | undefined;
                set((state) => {
                    redoAction = state.redoStack.shift();
                    if (redoAction) {
                        state.undoStack.push(redoAction);
                    }
                });
                return redoAction;
            },

            clearUndoRedo2D: () => {
                set((state) => {
                    state.undoStack = [];
                    state.redoStack = [];
                });
            },

            peekUndo2D: () => {
                const stack = get().undoStack;
                return stack.length > 0 ? stack[stack.length - 1] : undefined;
            },

            peekRedo2D: () => {
                const stack = get().redoStack;
                return stack.length > 0 ? stack[0] : undefined;
            },
        }))
    )
}

export type UndoRedo2DStoreType = ReturnType<typeof createUndoRedo2DStore>;