import { useFrame, useThree } from "@react-three/fiber";
import React, { useEffect, useState } from "react";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { useCamMode, useToggleView } from "../../../store/builder/store";
import { useKeyboardControls } from "@react-three/drei";
import switchToThirdPerson from "./switchToThirdPerson";
import switchToFirstPerson from "./switchToFirstPerson";
import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys";

const CamMode: React.FC = () => {
  const { camMode, setCamMode } = useCamMode();
  const [, get] = useKeyboardControls();
  const [isTransitioning, setIsTransitioning] = useState(false);
  const state: any = useThree();
  const { toggleView } = useToggleView();
  const [isShiftActive, setIsShiftActive] = useState(false);

  useEffect(() => {
    const handlePointerLockChange = async () => {
      if (document.pointerLockElement && !toggleView) {
        // Pointer is locked
      } else if (camMode === "FirstPerson" && !toggleView) {
        // Pointer is unlocked
        setCamMode("ThirdPerson");
        await switchToThirdPerson(state.controls, state.camera);
      }
    };

    document.addEventListener("pointerlockchange", handlePointerLockChange);

    return () => {
      document.removeEventListener(
        "pointerlockchange",
        handlePointerLockChange
      );
    };
  }, [camMode, toggleView, setCamMode, state.controls, state.camera]);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Shift") {
        setIsShiftActive(true);
      }
    };

    const handleKeyUp = (event: KeyboardEvent) => {
      if (event.key === "Shift") {
        setIsShiftActive(false);
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);

    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
    };
  }, []);

  useEffect(() => {
    const handleKeyPress = async (event: KeyboardEvent) => {
      if (!state.controls) return;

      const keyCombination = detectModifierKeys(event);

      if (keyCombination === "/" && !isTransitioning && !toggleView) {
        setIsTransitioning(true);

        state.controls.mouseButtons.left =
          CONSTANTS.controlsTransition.leftMouse;
        state.controls.mouseButtons.right =
          CONSTANTS.controlsTransition.rightMouse;
        state.controls.mouseButtons.wheel =
          CONSTANTS.controlsTransition.wheelMouse;
        state.controls.mouseButtons.middle =
          CONSTANTS.controlsTransition.middleMouse;

        if (camMode === "ThirdPerson") {
          setCamMode("FirstPerson");
          await switchToFirstPerson(state.controls, state.camera);
        } else if (camMode === "FirstPerson") {
          setCamMode("ThirdPerson");
          await switchToThirdPerson(state.controls, state.camera);
        }

        setIsTransitioning(false);
      }
    };

    window.addEventListener("keydown", handleKeyPress);
    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, [
    camMode,
    isTransitioning,
    toggleView,
    state.controls,
    state.camera,
    setCamMode,
  ]);

  useFrame(() => {
    const { forward, backward, left, right } = get();
    if (!state.controls) return;
    if (camMode === "ThirdPerson" || !document.pointerLockElement) return;

    const speedMultiplier = isShiftActive ? 4 : 1;

    if (forward) {
      state.controls.forward(
        CONSTANTS.firstPersonControls.forwardSpeed * speedMultiplier,
        true
      );
    }
    if (backward) {
      state.controls.forward(
        CONSTANTS.firstPersonControls.backwardSpeed * speedMultiplier,
        true
      );
    }
    if (left) {
      state.controls.truck(
        CONSTANTS.firstPersonControls.leftSpeed * speedMultiplier,
        0,
        true
      );
    }
    if (right) {
      state.controls.truck(
        CONSTANTS.firstPersonControls.rightSpeed * speedMultiplier,
        0,
        true
      );
    }
  });

  return null; // This component does not render any UI
};

export default CamMode;
