import React, { FC, useCallback, useEffect, useRef, useState } from "react";
import { AdditionalElementsWrapper, Triage } from "./AdditionalElements.styles";
import {
  getCordinates,
  calculateMapElementHeight,
  calculateMapElementWidth,
  calculateMapElementArc,
  checkPropInElement,
  getArc,
  getHeight,
  getWidth,
} from "./additionalHelper";
import {
  ADDITIONAL_TYPES,
  IAdditionalElements,
  IElementData,
  TAdditionalType,
} from "../../definitions/additional";

export const TriageElement: FC<IAdditionalElements> = ({
  element,
  scale,
  active,
  editMode,
  pdfHeight = 0,
  pdfWidth = 0,
  showDetails,
  saveChanges,
  focused,
  handleShortcut,
  inputFocused,
}) => {
  const pointRef = useRef<HTMLDivElement>(null);

  const [startPos, setStartPos] = useState({ x: 0, y: 0 });
  const [pointPos, setPointPos] = useState({ left: 0, top: 0 });

  const [elementData, setElementData] = useState<IElementData>({
    move: false,
    editMode: editMode,
    x: element.x,
    y: element.y,
    elementMode: element.type,
    pageHeight: pdfHeight,
    pageWidth: pdfWidth,
    rotate: getArc(element),
    width: getWidth(element),
    height: getHeight(element),
    size: (checkPropInElement(element, "size", "number") as number) || 0,
    end_x: (checkPropInElement(element, "end_x", "number") as number) || 0,
    end_y: (checkPropInElement(element, "end_y", "number") as number) || 0,
    mode: "element",
    scale: 1,
    scaleAction: false,
    rotateAction: false,
  });

  const updateElement = useCallback(() => {
    saveChanges(
      {
        ...element,
        x: elementData.x,
        y: elementData.y,
        end_x: elementData.end_x,
        end_y: elementData.end_y,
        size: elementData.size,
        rotation: elementData.rotate,
        height: elementData.height,
      },
      false
    );
  }, [element, elementData, saveChanges]);

  const startMove = useCallback(
    (event: MouseEvent) => {
      event.stopPropagation();
      if (element.lock) return;

      showDetails(element.id!, true, false);
      setStartPos({ x: event.clientX, y: event.clientY });
      setPointPos({
        left: elementData.x * elementData.scale,
        top: elementData.y * elementData.scale,
      });
      setElementData((prev) => ({
        ...prev,
        size: element.size,
        rotate: element.rotation,
        move: true,
      }));
    },
    [element, elementData, showDetails]
  );
  const move = useCallback(
    (event: MouseEvent) => {
      if (!elementData.move || element.lock) return;
      event.stopPropagation();
      const newDelta = {
        left: event.clientX - startPos.x,
        top: event.clientY - startPos.y,
      };

      setElementData((prev) => ({
        ...prev,
        x: (pointPos.left + newDelta.left) / elementData.scale,
        y: (pointPos.top + newDelta.top) / elementData.scale,
      }));
    },
    [elementData.move, element.lock, element.height, startPos, pointPos]
  );

  const endMove = useCallback(
    (event: MouseEvent) => {
      if (!elementData.move) return;
      event.stopPropagation();
      setElementData((prev) => ({
        ...prev,
        move: false,
      }));

      updateElement();
    },
    [elementData.move, updateElement]
  );

  const shortScope = ["x", "X", "Backspace", "Delete"];

  useEffect(() => {
    const point = pointRef.current;
    if (!point) return;
    const handleKeyDown = (e: KeyboardEvent) => {
      if (active && !inputFocused) {
        if (shortScope.includes(e.key)) {
          handleShortcut("delete", element.id, "mapElement");
        }
      }
    };

    point.addEventListener("mousedown", startMove);
    window.addEventListener("mousemove", move, { passive: true });
    window.addEventListener("mouseup", endMove);
    window.addEventListener("mouseleave", endMove);
    document.addEventListener("keydown", handleKeyDown);

    return () => {
      point.removeEventListener("mousedown", startMove);
      window.removeEventListener("mousemove", move);
      window.removeEventListener("mouseup", endMove);
      window.removeEventListener("mouseleave", endMove);
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, [startMove, move, endMove]);

  useEffect(() => {
    setElementData((prev) => ({
      ...prev,
      x: element.x,
      y: element.y,
      width: getWidth(element),
      height: getHeight(element),
      pageHeight: pdfHeight,
      pageWidth: pdfWidth,
      editMode: editMode,
      rotate: element.rotation,
      scale: scale,
    }));
  }, [element, pdfHeight, pdfWidth, scale, editMode]);

  return (
    <AdditionalElementsWrapper
      isActive={false}
      isEditMode={elementData.editMode}
      origin={element.type === "edge"}
      style={{
        left:
          getCordinates(
            elementData.x * elementData.scale,
            elementData.width * elementData.scale,
            ADDITIONAL_TYPES.dot as TAdditionalType
          ) + "px",
        top:
          getCordinates(
            elementData.y * elementData.scale,
            elementData.height * elementData.scale,
            ADDITIONAL_TYPES.dot as TAdditionalType
          ) + "px",
        height: `${
          calculateMapElementHeight(elementData) * elementData.scale
        }px`,
        width: `${calculateMapElementWidth(elementData) * elementData.scale}px`,
        transform: `rotate(${calculateMapElementArc(elementData)}deg)`,
      }}
    >
      <Triage
        ref={pointRef}
        isActive={active || focused}
        size={elementData.width * elementData.scale}
      />
    </AdditionalElementsWrapper>
  );
};
