import React, { useState, useEffect } from 'react';

import OuterRect from '../OuterRect';
import {
  svgPath,
  bezierCommand,
  controlPoint,
  line,
} from '../../helpers/svgBezierCurve';
import { pointCalc, rectCalcWithPoint, calcViewBox } from '../../helpers/brush';

import { AnnotationContainer } from '../../global/otherStyled';
import { SVG } from './styled';

const Ink: React.FC<AnnotationElementPropsType> = ({
  obj_attr: { position, bdcolor, bdwidth = 0, transparency },
  isCollapse,
  onUpdate,
  viewport,
  scale,
  id,
}: AnnotationElementPropsType) => {
  const [points, setPoints] = useState<PointType[][]>([]);
  const [rect, setRect] = useState({ top: 0, left: 0, width: 0, height: 0 });
  const [moving, setMoving] = useState(false);

  const borderWidth = bdwidth * scale;

  const handleScaleOrMove = ({
    top,
    left,
    width = 0,
    height = 0,
  }: CoordType): void => {
    setMoving(true);

    setRect((currentRect) => {
      const rx = width / currentRect.width;
      const ry = height / currentRect.height;
      const dx = left - currentRect.left;
      const dy = currentRect.top - top;
      let disX = 0;
      let disY = 0;

      setPoints((currentPoint) => {
        const newRect = rectCalcWithPoint(currentPoint, borderWidth);
        disX = newRect.left - left;
        disY = newRect.top - top;

        const newPoints = (currentPoint as PointType[][])[0].map((ele) => {
          let x = (ele.x + dx) * rx;
          let y = (ele.y - dy) * ry;

          if (rx !== 1) {
            x = x - disX;
          }
          if (ry !== 1) {
            y = y - disY + 5;
          }

          return {
            x,
            y,
          };
        });
        return [newPoints];
      });

      return { top, left, width, height };
    });
  };

  const handleMouseUp = () => {
    setMoving(false);
  };

  useEffect(() => {
    const newPoints = pointCalc(
      position as PointType[][],
      viewport.height,
      scale,
    );
    const newRect = rectCalcWithPoint(newPoints, borderWidth);
    setPoints(newPoints);
    setRect(newRect);
  }, [viewport, scale]);

  useEffect(() => {
    if (!moving && points[0]) {
      const newPoints = (points as PointType[][])[0].map((ele) => ({
        x: ele.x / scale,
        y: (viewport.height - ele.y) / scale,
      }));

      onUpdate({
        position: [newPoints],
      });
    }
  }, [moving, points]);

  return (
    <>
      <AnnotationContainer
        id={id}
        top={`${rect.top}px`}
        left={`${rect.left}px`}
        width={`${rect.width}px`}
        height={`${rect.height}px`}
      >
        <SVG viewBox={calcViewBox(rect, borderWidth)}>
          {points.map((ele: PointType[], index: number) => {
            const key = `${id}_path_${index}`;
            return (
              <path
                key={key}
                d={svgPath(
                  ele as PointType[],
                  bezierCommand(controlPoint(line, 0.2)),
                )}
                fill="none"
                stroke={bdcolor}
                strokeWidth={borderWidth}
                strokeOpacity={transparency}
              />
            );
          })}
        </SVG>
      </AnnotationContainer>
      {!isCollapse ? (
        <OuterRect
          top={rect.top}
          left={rect.left}
          width={rect.width}
          height={rect.height}
          onMove={handleScaleOrMove}
          onScale={handleScaleOrMove}
          onMouseUp={handleMouseUp}
        />
      ) : (
        ''
      )}
    </>
  );
};

export default Ink;
