import Konva from 'konva';
import { isNumber } from 'lodash-es';
import React from 'react';
import { KonvaNodeEvents } from 'react-konva';

function standardizeRectConfig(config: Konva.RectConfig): Konva.RectConfig {
  if (config.width < 0) {
    config.width = Math.abs(config.width);
    config.x -= config.width;
  }

  if (config.height < 0) {
    config.height = Math.abs(config.height);
    config.y -= config.height;
  }

  return config;
}

function ensureEvtWithLayer(
  evt: any,
): evt is MouseEvent & { layerX: number; layerY: number } {
  return (
    isNumber(evt.layerX) && isNumber(evt.layerY) && evt instanceof MouseEvent
  );
}

export function useDrawStage({
  canDraw = true,
  onFinish,
}: {
  canDraw?: boolean;
  onFinish?(config: Konva.RectConfig): void;
}) {
  const [isDrawing, setDrawing] = React.useState(false);
  const [rectConfig, setRectConfig] = React.useState<Konva.RectConfig>({
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    stroke: 'red',
    fill: 'rgba(255,0,0,0.2)',
    strokeWidth: 4,
    visible: false,
    isAnchor: false,
  });

  const start: KonvaNodeEvents['onMouseDown'] = React.useCallback(
    (event) => {
      const evt = event.evt;
      if (
        canDraw &&
        event.target.id() === 'background-image' &&
        ensureEvtWithLayer(evt)
      ) {
        const stage = event.currentTarget.getStage();

        setDrawing(true);
        setRectConfig((prevConfig) => ({
          ...prevConfig,
          x: evt.layerX / stage.scaleX(),
          y: evt.layerY / stage.scaleY(),
        }));
      }
    },
    [canDraw],
  );

  const handle: KonvaNodeEvents['onMouseMove'] = React.useCallback(
    (event) => {
      const evt = event.evt;
      if (canDraw && isDrawing && ensureEvtWithLayer(evt)) {
        const stage = event.currentTarget.getStage();
        setRectConfig((prevConfig) => ({
          ...prevConfig,
          width: evt.layerX / stage.scaleX() - prevConfig.x,
          height: evt.layerY / stage.scaleY() - prevConfig.y,
          visible: true,
        }));
      }
    },
    [canDraw, isDrawing],
  );

  const finish: KonvaNodeEvents['onMouseUp'] = React.useCallback(() => {
    if (canDraw && isDrawing) {
      setDrawing(false);
      setRectConfig((prevConfig) => ({
        ...prevConfig,
        width: 0,
        height: 0,
        visible: false,
      }));
      if (onFinish && rectConfig.width && rectConfig.height) {
        onFinish(standardizeRectConfig(rectConfig));
      }
    }
  }, [canDraw, onFinish]);

  return {
    start,
    handle,
    finish,
    isDrawing,
    rect: rectConfig,
  };
}
