import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import * as THREE from 'three';

interface SelectedEventSphereState {
    selectedEventSphere: THREE.Mesh | null;
    setSelectedEventSphere: (mesh: THREE.Mesh | null) => void;
    clearSelectedEventSphere: () => void;
}

export const useSelectedEventSphere = create<SelectedEventSphereState>()(
    immer((set) => ({
        selectedEventSphere: null,
        setSelectedEventSphere: (mesh) => {
            set((state) => {
                state.selectedEventSphere = mesh;
            });
        },
        clearSelectedEventSphere: () => {
            set((state) => {
                state.selectedEventSphere = null;
            });
        },
    }))
);

interface DeletableEventSphereState {
    deletableEventSphere: THREE.Mesh | null;
    setDeletableEventSphere: (mesh: THREE.Mesh | null) => void;
    clearDeletableEventSphere: () => void;
}

export const useDeletableEventSphere = create<DeletableEventSphereState>()(
    immer((set) => ({
        deletableEventSphere: null,
        setDeletableEventSphere: (mesh) => {
            set((state) => {
                state.deletableEventSphere = mesh;
            });
        },
        clearDeletableEventSphere: () => {
            set((state) => {
                state.deletableEventSphere = null;
            });
        },
    }))
);

interface SelectedEventDataState {
    selectedEventData: { data: EventsSchema; selectedPoint: string } | undefined;
    setSelectedEventData: (data: EventsSchema, selectedPoint: string) => void;
    clearSelectedEventData: () => void;
}

export const useSelectedEventData = create<SelectedEventDataState>()(
    immer((set) => ({
        selectedEventData: undefined,
        setSelectedEventData: (data, selectedPoint) => {
            set((state) => {
                state.selectedEventData = { data, selectedPoint };
            });
        },
        clearSelectedEventData: () => {
            set((state) => {
                state.selectedEventData = undefined;
            });
        },
    }))
);

interface SelectedAssetState {
    selectedAsset: EventsSchema | undefined;
    setSelectedAsset: (EventData: EventsSchema) => void;
    clearSelectedAsset: () => void;
}

export const useSelectedAsset = create<SelectedAssetState>()(
    immer((set) => ({
        selectedAsset: undefined,
        setSelectedAsset: (EventData) => {
            set((state) => {
                state.selectedAsset = EventData;
            });
        },
        clearSelectedAsset: () => {
            set((state) => {
                state.selectedAsset = undefined;
            });
        },
    }))
);

interface SelectedProductState {
    selectedProduct: { productUuid: string; productName: string };
    setSelectedProduct: (productUuid: string, productName: string) => void;
    clearSelectedProduct: () => void;
}

export const createSelectedProductStore = () => {
    return create<SelectedProductState>()(
        immer((set) => ({
            selectedProduct: { productUuid: '', productName: '' },
            setSelectedProduct: (productUuid, productName) => {
                set((state) => {
                    state.selectedProduct.productUuid = productUuid;
                    state.selectedProduct.productName = productName;
                });
            },
            clearSelectedProduct: () => {
                set((state) => {
                    state.selectedProduct.productUuid = '';
                    state.selectedProduct.productName = '';
                });
            },
        }))
    )
}

export type SelectedProductType = ReturnType<typeof createSelectedProductStore>;

interface SelectedVersionState {
    selectedVersion: Version | null;
    setSelectedVersion: (version: Version) => void;
    clearSelectedVersion: () => void;
}

export const createSelectedVersionStore = () => {
    return create<SelectedVersionState>()(
        immer((set) => ({
            selectedVersion: null,
            setSelectedVersion: (version) => {
                set((state) => {
                    state.selectedVersion = version;
                });
            },
            clearSelectedVersion: () => {
                set((state) => {
                    state.selectedVersion = null;
                });
            },
        }))
    )
}

export type SelectedVersionType = ReturnType<typeof createSelectedVersionStore>;

interface SelectedActionState {
    selectedAction: { actionId: string | null; actionName: string | null };
    setSelectedAction: (actionId: string, actionName: string) => void;
    clearSelectedAction: () => void;
}

export const useSelectedAction = create<SelectedActionState>()(
    immer((set) => ({
        selectedAction: { actionId: null, actionName: null },
        setSelectedAction: (actionId, actionName) => {
            set((state) => {
                state.selectedAction.actionId = actionId;
                state.selectedAction.actionName = actionName;
            });
        },
        clearSelectedAction: () => {
            set((state) => {
                state.selectedAction.actionId = null;
                state.selectedAction.actionName = null;
            });
        },
    }))
);

interface SelectedAnimationState {
    selectedAnimation: {
        animationUuid: string;
        animationName: string;
        animationType: "behaviour" | "animatedTravel";
        animation: string | null;
        travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
    } | null;
    setSelectedAnimation: (animation: {
        animationUuid: string;
        animationName: string;
        animationType: "behaviour" | "animatedTravel";
        animation: string | null;
        travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
    }) => void;
    clearSelectedAnimation: () => void;
}

export const useSelectedAnimation = create<SelectedAnimationState>()(
    immer((set) => ({
        selectedAnimation: null,
        setSelectedAnimation: (animation) => {
            set((state) => {
                state.selectedAnimation = animation;
            });
        },
        clearSelectedAnimation: () => {
            set((state) => {
                state.selectedAnimation = null;
            });
        },
    }))
);

interface IsDraggingState {
    isDragging: "start" | "end" | "assembly" | null;
    setIsDragging: (state: "start" | "end" | "assembly" | null) => void;
}

export const useIsDragging = create<IsDraggingState>()(
    immer((set) => ({
        isDragging: null,
        setIsDragging: (state) => {
            set((s) => {
                s.isDragging = state;
            });
        },
    }))
);

interface IsRotatingState {
    isRotating: "start" | "end" | "assembly" | null;
    setIsRotating: (state: "start" | "end" | "assembly" | null) => void;
}

export const useIsRotating = create<IsRotatingState>()(
    immer((set) => ({
        isRotating: null,
        setIsRotating: (state) => {
            set((s) => {
                s.isRotating = state;
            });
        },
    }))
);

interface MainProductState {
    mainProduct: { productUuid: string; productName: string } | null;
    setMainProduct: (productUuid: string, productName: string) => void;
    clearMainProduct: () => void;
}

export const useMainProduct = create<MainProductState>()(
    immer((set) => ({
        mainProduct: null,
        setMainProduct: (productUuid: string, productName: string) => {
            set((state) => {
                state.mainProduct = { productUuid, productName };
            });
        },
        clearMainProduct: () => {
            set((state) => {
                state.mainProduct = null;
            });
        },
    }))
);

interface ComparisonProductState {
    comparisonProduct: { productUuid: string; productName: string } | null;
    setComparisonProduct: (productUuid: string, productName: string) => void;
    clearComparisonProduct: () => void;
}

export const useComparisonProduct = create<ComparisonProductState>()(
    immer((set) => ({
        comparisonProduct: null,
        setComparisonProduct: (productUuid: string, productName: string) => {
            set((state) => {
                state.comparisonProduct = { productUuid, productName };
            });
        },
        clearComparisonProduct: () => {
            set((state) => {
                state.comparisonProduct = null;
            });
        },
    }))
);

interface SelectedPointsState {
    selectedPoints: THREE.Object3D[];
    setSelectedPoints: (points: THREE.Object3D[]) => void;
    addSelectedPoint: (point: THREE.Object3D) => void;
    removeSelectedPoint: (uuid: string) => void;
    clearSelectedPoints: () => void;
}

export const useSelectedPoints = create<SelectedPointsState>()(
    immer((set) => ({
        selectedPoints: [],
        setSelectedPoints: (points) => {
            set((state) => {
                state.selectedPoints = points;
            });
        },
        addSelectedPoint: (point) => {
            set((state) => {
                if (!state.selectedPoints.find(p => p.uuid === point.uuid)) {
                    state.selectedPoints.push(point);
                }
            });
        },
        removeSelectedPoint: (uuid) => {
            set((state) => {
                state.selectedPoints = state.selectedPoints.filter(p => p.uuid !== uuid);
            });
        },
        clearSelectedPoints: () => {
            set((state) => {
                state.selectedPoints = [];
            });
        },
    }))
);