import * as THREE from "three";
import * as Types from "../types/world/worldTypes";
import { create } from "zustand";
import { io } from "socket.io-client";

export const useSocketStore = create<any>((set: any, get: any) => ({
  socket: null,
  initializeSocket: (email: string, organization: string) => {
    const existingSocket = get().socket;
    if (existingSocket) {
      return;
    }

    const socket = io(
      `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`,
      {
        reconnection: true,
        auth: { email, organization },
      }
    );

    const visualizationSocket = io(
      `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`,
      {
        reconnection: true,
        auth: { email, organization },
      }
    );

    set({ socket, visualizationSocket });
  },
  disconnectSocket: () => {
    set((state: any) => {
      state.socket?.disconnect();
      state.visualizationSocket?.disconnect();
      return { socket: null };
    });
  },
}));

export const useLoadingProgress = create<{
  loadingProgress: number;
  setLoadingProgress: (x: number) => void;
}>((set) => ({
  loadingProgress: 1,
  setLoadingProgress: (x: number) => set({ loadingProgress: x }),
}));

export const useOrganization = create<any>((set: any) => ({
  organization: "",
  setOrganization: (x: any) => set(() => ({ organization: x })),
}));

export const useToggleView = create<any>((set: any) => ({
  toggleView: false,
  setToggleView: (x: any) => set(() => ({ toggleView: x })),
}));

export const useUpdateScene = create<any>((set: any) => ({
  updateScene: false,
  setUpdateScene: (x: any) => set(() => ({ updateScene: x })),
}));

export const useWalls = create<any>((set: any) => ({
  walls: [],
  setWalls: (x: any) => set(() => ({ walls: x })),
}));

export const useZones = create<any>((set: any) => ({
  zones: [],
  setZones: (x: any) => set(() => ({ zones: x })),
}));

interface ZonePointsState {
  zonePoints: THREE.Vector3[];
  setZonePoints: (points: THREE.Vector3[]) => void;
}

export const useZonePoints = create<ZonePointsState>((set) => ({
  zonePoints: [],
  setZonePoints: (points) => set({ zonePoints: points }),
}));

export const useSelectedItem = create<any>((set: any) => ({
  selectedItem: { name: "", id: "" },
  setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
}));

export const useSelectedAssets = create<any>((set: any) => ({
  selectedAssets: [],
  setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
}));

export const useLayers = create<any>((set: any) => ({
  Layers: 1,
  setLayers: (x: any) => set(() => ({ Layers: x })),
}));

export const useCamPosition = create<any>((set: any) => ({
  camPosition: { x: undefined, y: undefined, z: undefined },
  setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
}));

export const useMenuVisible = create<any>((set: any) => ({
  menuVisible: false,
  setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
}));

export const useDeleteModels = create<any>((set: any) => ({
  deleteModels: false,
  setDeleteModels: (x: any) => set(() => ({ deleteModels: x })),
}));

export const useToolMode = create<any>((set: any) => ({
  toolMode: null,
  setToolMode: (x: any) => set(() => ({ toolMode: x })),
}));

export const useNewLines = create<any>((set: any) => ({
  newLines: [],
  setNewLines: (x: any) => set(() => ({ newLines: x })),
}));

export const useDeletedLines = create<any>((set: any) => ({
  deletedLines: [],
  setDeletedLines: (x: any) => set(() => ({ deletedLines: x })),
}));

export const useMovePoint = create<any>((set: any) => ({
  movePoint: false,
  setMovePoint: (x: any) => set(() => ({ movePoint: x })),
}));

export const useTransformMode = create<any>((set: any) => ({
  transformMode: null,
  setTransformMode: (x: any) => set(() => ({ transformMode: x })),
}));

export const useDeletePointOrLine = create<any>((set: any) => ({
  deletePointOrLine: false,
  setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })),
}));

export const useFloorItems = create<any>((set: any) => ({
  floorItems: null,
  setFloorItems: (callback: any) =>
    set((state: any) => ({
      floorItems:
        typeof callback === "function" ? callback(state.floorItems) : callback,
    })),
}));

export const useWallItems = create<any>((set: any) => ({
  wallItems: [],
  setWallItems: (callback: any) =>
    set((state: any) => ({
      wallItems:
        typeof callback === "function" ? callback(state.wallItems) : callback,
    })),
}));

export const useSelectedWallItem = create<any>((set: any) => ({
  selectedWallItem: null,
  setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
}));

export const useselectedFloorItem = create<any>((set: any) => ({
  selectedFloorItem: null,
  setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
}));

export const useDeletableFloorItem = create<any>((set: any) => ({
  deletableFloorItem: null,
  setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
}));

export const useSetScale = create<any>((set: any) => ({
  scale: null,
  setScale: (x: any) => set(() => ({ scale: x })),
}));

export const useRoofVisibility = create<any>((set: any) => ({
  roofVisibility: false,
  setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
}));

export const useWallVisibility = create<any>((set: any) => ({
  wallVisibility: false,
  setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
}));

export const useShadows = create<any>((set: any) => ({
  shadows: false,
  setShadows: (x: any) => set(() => ({ shadows: x })),
}));

export const useSunPosition = create<any>((set: any) => ({
  sunPosition: { x: undefined, y: undefined, z: undefined },
  setSunPosition: (newSuntPosition: any) =>
    set({ sunPosition: newSuntPosition }),
}));

export const useRemoveLayer = create<any>((set: any) => ({
  removeLayer: false,
  setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
}));

export const useRemovedLayer = create<any>((set: any) => ({
  removedLayer: null,
  setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
}));

export const useActiveLayer = create<any>((set: any) => ({
  activeLayer: 1,
  setActiveLayer: (x: any) => set({ activeLayer: x }),
}));

interface RefTextUpdateState {
  refTextupdate: number;
  setRefTextUpdate: (
    callback: (currentValue: number) => number | number
  ) => void;
}

export const useRefTextUpdate = create<RefTextUpdateState>((set) => ({
  refTextupdate: -1000,
  setRefTextUpdate: (callback) =>
    set((state) => ({
      refTextupdate:
        typeof callback === "function"
          ? callback(state.refTextupdate)
          : callback,
    })),
}));

export const useResetCamera = create<any>((set: any) => ({
  resetCamera: false,
  setResetCamera: (x: any) => set({ resetCamera: x }),
}));

export const useAddAction = create<any>((set: any) => ({
  addAction: null,
  setAddAction: (x: any) => set({ addAction: x }),
}));

export const useActiveTool = create<any>((set: any) => ({
  activeTool: "cursor",
  setActiveTool: (x: any) => set({ activeTool: x }),
}));

export const use2DUndoRedo = create<any>((set: any) => ({
  is2DUndoRedo: null,
  set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
}));

export const useElevation = create<any>((set: any) => ({
  elevation: 45,
  setElevation: (x: any) => set({ elevation: x }),
}));

export const useAzimuth = create<any>((set: any) => ({
  azimuth: -160,
  setAzimuth: (x: any) => set({ azimuth: x }),
}));

export const useRenderDistance = create<any>((set: any) => ({
  renderDistance: 40,
  setRenderDistance: (x: any) => set({ renderDistance: x }),
}));

export const useCamMode = create<any>((set: any) => ({
  camMode: "ThirdPerson",
  setCamMode: (x: any) => set({ camMode: x }),
}));

export const useUserName = create<any>((set: any) => ({
  userName: "",
  setUserName: (x: any) => set({ userName: x }),
}));

export const useObjectPosition = create<any>((set: any) => ({
  objectPosition: { x: undefined, y: undefined, z: undefined },
  setObjectPosition: (newObjectPosition: any) =>
    set({ objectPosition: newObjectPosition }),
}));

export const useObjectScale = create<any>((set: any) => ({
  objectScale: { x: undefined, y: undefined, z: undefined },
  setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }),
}));

export const useObjectRotation = create<any>((set: any) => ({
  objectRotation: { x: undefined, y: undefined, z: undefined },
  setObjectRotation: (newObjectRotation: any) =>
    set({ objectRotation: newObjectRotation }),
}));

export const useDrieTemp = create<any>((set: any) => ({
  drieTemp: undefined,
  setDrieTemp: (x: any) => set({ drieTemp: x }),
}));

export const useActiveUsers = create<any>((set: any) => ({
  activeUsers: [],
  setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
    set((state: { activeUsers: any[] }) => ({
      activeUsers:
        typeof callback === "function"
          ? callback(state.activeUsers)
          : callback,
    })),
}));

export const useDrieUIValue = create<any>((set: any) => ({
  drieUIValue: { touch: null, temperature: null, humidity: null },

  setDrieUIValue: (x: any) =>
    set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),

  setTouch: (value: any) =>
    set((state: any) => ({
      drieUIValue: { ...state.drieUIValue, touch: value },
    })),
  setTemperature: (value: any) =>
    set((state: any) => ({
      drieUIValue: { ...state.drieUIValue, temperature: value },
    })),
  setHumidity: (value: any) =>
    set((state: any) => ({
      drieUIValue: { ...state.drieUIValue, humidity: value },
    })),
}));

export const useDrawMaterialPath = create<any>((set: any) => ({
  drawMaterialPath: false,
  setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }),
}));

export const useSelectedActionSphere = create<any>((set: any) => ({
  selectedActionSphere: undefined,
  setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }),
}));

export const useSelectedPath = create<any>((set: any) => ({
  selectedPath: undefined,
  setSelectedPath: (x: any) => set({ selectedPath: x }),
}));

interface SimulationPathsStore {
  simulationStates: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[];
  setSimulationStates: (
    paths:
      | (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]
      | ((prev: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]
      ) => (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[])
  ) => void;
}

export const useSimulationStates = create<SimulationPathsStore>((set) => ({
  simulationStates: [],
  setSimulationStates: (paths) =>
    set((state) => ({
      simulationStates:
        typeof paths === "function" ? paths(state.simulationStates) : paths,
    })),
}))

export const useNavMesh = create<any>((set: any) => ({
  navMesh: null,
  setNavMesh: (x: any) => set({ navMesh: x }),
}));

export const useIsConnecting = create<any>((set: any) => ({
  isConnecting: false,
  setIsConnecting: (x: any) => set({ isConnecting: x }),
}));

export const useStartSimulation = create<any>((set: any) => ({
  startSimulation: false,
  setStartSimulation: (x: any) => set({ startSimulation: x }),
}));

export const useEyeDropMode = create<any>((set: any) => ({
  eyeDropMode: false,
  setEyeDropMode: (x: any) => set({ eyeDropMode: x }),
}));

export const useEditingPoint = create<any>((set: any) => ({
  editingPoint: false,
  setEditingPoint: (x: any) => set({ editingPoint: x }),
}));

export const usePreviewPosition = create<{
  previewPosition: { x: number; y: number } | null;
  setPreviewPosition: (position: { x: number; y: number } | null) => void;
}>((set) => ({
  previewPosition: null,
  setPreviewPosition: (position) => set({ previewPosition: position }),
}));

export const usezoneTarget = create<any>((set: any) => ({
  zoneTarget: [],
  setZoneTarget: (x: any) => set({ zoneTarget: x }),
}));

export const usezonePosition = create<any>((set: any) => ({
  zonePosition: [],
  setZonePosition: (x: any) => set({ zonePosition: x }),
}));

interface EditPositionState {
  Edit: boolean;
  setEdit: (value: boolean) => void;
}

export const useEditPosition = create<EditPositionState>((set) => ({
  Edit: false,
  setEdit: (value) => set({ Edit: value }), // Properly updating the state
}));

export const useAsset3dWidget = create<any>((set: any) => ({
  widgetSelect: "",
  setWidgetSelect: (x: any) => set({ widgetSelect: x }),
}));

export const useWidgetSubOption = create<any>((set: any) => ({
  widgetSubOption: "2D",
  setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
}));
export const useLimitDistance = create<any>((set: any) => ({
  limitDistance: true,
  setLimitDistance: (x: any) => set({ limitDistance: x }),
}));

export const useTileDistance = create<any>((set: any) => ({
  gridValue: { size: 300, divisions: 75 },
  planeValue: { height: 300, width: 300 },

  setGridValue: (value: any) =>
    set((state: any) => ({
      gridValue: { ...state.gridValue, ...value },
    })),

  setPlaneValue: (value: any) =>
    set((state: any) => ({
      planeValue: { ...state.planeValue, ...value },
    })),
}));

// Define the Asset type
type Asset = {
  id: string;
  name: string;
  position?: [number, number, number]; // Optional: 3D position
  rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation
};

// Zustand store type
type ZoneAssetState = {
  zoneAssetId: Asset | null;
  setZoneAssetId: (asset: Asset | null) => void;
};

// Zustand store
export const useZoneAssetId = create<ZoneAssetState>((set) => ({
  zoneAssetId: null,
  setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
}));