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

type UndoRedo3DStore = {
    undoStack: UndoRedo3DTypes[];
    redoStack: UndoRedo3DTypes[];

    push3D: (entry: UndoRedo3DTypes) => void;
    undo3D: () => UndoRedo3DTypes | undefined;
    redo3D: () => UndoRedo3DTypes | undefined;
    clearUndoRedo3D: () => void;

    peekUndo3D: () => UndoRedo3DTypes | undefined;
    peekRedo3D: () => UndoRedo3DTypes | undefined;
};

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

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

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

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

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

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

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

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

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

export type UndoRedo3DStoreType = ReturnType<typeof createUndoRedo3DStore>;