import React from 'react';
import { v4 as uuidv4 } from 'uuid';

import Outer from '../OuterRectForLine';
import {
  AnnotationElementPropsType,
  LinePositionType,
  HTMLCoordinateType,
} from '../../constants/type';
import { parsePositionForBackend } from '../../helpers/position';

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

const Note: React.SFC<AnnotationElementPropsType> = ({
  obj_type,
  obj_attr,
  scale,
  viewport,
  isCollapse,
  onUpdate,
}: AnnotationElementPropsType) => {
  const {
    bdcolor = '',
    bdwidth = 0,
    transparency = 0,
    position,
    is_arrow,
  } = obj_attr;
  const uuid = uuidv4();

  const getActualPoint = (
    { start, end }: LinePositionType,
    h: number,
    s: number
  ): LinePositionType => {
    const x1 = start.x * scale;
    const y1 = h - start.y * s;
    const x2 = end.x * scale;
    const y2 = h - end.y * s;
    return {
      start: {
        x: x1,
        y: y1,
      },
      end: {
        x: x2,
        y: y2,
      },
    };
  };

  const pointCalc = (
    { start, end }: LinePositionType,
    borderWidth: number
  ): LinePositionType => ({
    start: {
      x: start.x + borderWidth,
      y: start.y + borderWidth,
    },
    end: {
      x: end.x + borderWidth,
      y: end.y + borderWidth,
    },
  });

  const rectCalc = (
    { start, end }: LinePositionType,
    h: number,
    s: number
  ): HTMLCoordinateType => {
    const startY = h - start.y * s;
    const endY = h - end.y * s;

    return {
      top: startY > endY ? endY : startY,
      left: start.x > end.x ? end.x * s : start.x * s,
      width: Math.abs((end.x - start.x) * s),
      height: Math.abs(endY - startY),
    };
  };

  const actualbdwidth = bdwidth * scale;
  const annotRect = rectCalc(
    position as LinePositionType,
    viewport.height,
    scale
  );
  const { start, end } = getActualPoint(
    position as LinePositionType,
    viewport.height,
    scale
  );
  const { start: completeStart, end: completeEnd } = pointCalc(
    { start, end } as LinePositionType,
    actualbdwidth
  );

  const actualWidth = annotRect.width + actualbdwidth + 15;
  const actualHeight = annotRect.height + actualbdwidth + 15;

  const handleMove = ({
    start: moveStart,
    end: moveEnd,
  }: LinePositionType): void => {
    const newPosition = {
      start: {
        x: moveStart.x,
        y: moveStart.y,
      },
      end: {
        x: moveEnd.x,
        y: moveEnd.y,
      },
    };

    onUpdate({
      position: parsePositionForBackend(
        obj_type,
        newPosition,
        viewport.height,
        scale
      ),
    });
  };

  return (
    <>
      <AnnotationContainer
        top={`${annotRect.top}px`}
        left={`${annotRect.left}px`}
        width={`${actualWidth}px`}
        height={`${actualHeight}px`}
      >
        <svg
          width={`${actualWidth}px`}
          height={`${actualHeight}px`}
          viewBox={`${annotRect.left} ${annotRect.top} ${actualWidth} ${actualHeight}`}
        >
          {is_arrow ? (
            <defs>
              <marker
                id={uuid}
                markerWidth={actualbdwidth * 2}
                markerHeight={actualbdwidth * 3}
                refX={3}
                refY={2}
                orient="auto"
                markerUnits="strokeWidth"
              >
                <polyline
                  points="0.25,0.5 3.25,2 0.25,3.5 3.25,2 -0.25,2"
                  stroke={bdcolor}
                  strokeWidth={1}
                  fill="none"
                  strokeDasharray={100}
                />
              </marker>
            </defs>
          ) : null}
          <line
            x1={completeStart.x}
            y1={completeStart.y}
            x2={completeEnd.x}
            y2={completeEnd.y}
            stroke={bdcolor}
            strokeWidth={actualbdwidth}
            strokeOpacity={transparency}
            markerEnd={is_arrow ? `url(#${uuid})` : ''}
          />
        </svg>
      </AnnotationContainer>
      {!isCollapse ? (
        <Outer
          top={annotRect.top}
          left={annotRect.left}
          width={actualWidth}
          height={actualHeight}
          start={start}
          end={end}
          completeStart={completeStart}
          completeEnd={completeEnd}
          onMove={handleMove}
        />
      ) : (
        ''
      )}
    </>
  );
};

export default Note;
