import * as React from 'react';
import { NOTCHES_LENGTH } from '../../../utils/default';

interface IDimensionProps {
  id: string
  xStart: number
  yStart: number
  xEnd: number
  yEnd: number
  text: string
  strokeWidth: number
  scale?: number
}

/**
 * 2D Parametric function. Returns a new coordinate from the origin coordinate
 * See for more details https://en.wikipedia.org/wiki/Parametric_equation.
 * TL;DR a parametric function is a function with a parameter
 * @param x0 Origin coordinate
 * @param t The parameter
 * @param vx Transform vector
 * @returns Returns a new coordinate from the origin coordinate
 */
function ApplyParametric(x0: number, t: number, vx: number): number {
  return x0 + t * vx;
}

export function Dimension(props: IDimensionProps): JSX.Element {
  const scale = props.scale ?? 1;
  const style: React.CSSProperties = {
    stroke: 'black',
    strokeWidth: 2 / scale
  };

  /// We need to find the points of the notches
  // Get the vector of the line
  const [deltaX, deltaY] = [(props.xEnd - props.xStart), (props.yEnd - props.yStart)];
  const rotation = (Math.atan2(deltaY, deltaX) / (2 * Math.PI));

  // Get the unit vector
  const norm = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
  const [unitX, unitY] = [deltaX / norm, deltaY / norm];

  // Get the perpandicular vector
  const [perpVecX, perpVecY] = [unitY, -unitX];

  // Use the parametric function to get the coordinates (x = x0 + t * v.x)
  const notchesLength = NOTCHES_LENGTH / scale;
  const startTopX = ApplyParametric(props.xStart, notchesLength, perpVecX);
  const startTopY = ApplyParametric(props.yStart, notchesLength, perpVecY);
  const startBottomX = ApplyParametric(props.xStart, -notchesLength, perpVecX);
  const startBottomY = ApplyParametric(props.yStart, -notchesLength, perpVecY);

  const endTopX = ApplyParametric(props.xEnd, notchesLength, perpVecX);
  const endTopY = ApplyParametric(props.yEnd, notchesLength, perpVecY);
  const endBottomX = ApplyParametric(props.xEnd, -notchesLength, perpVecX);
  const endBottomY = ApplyParametric(props.yEnd, -notchesLength, perpVecY);

  return (
    <g key={props.id}>
      <line
        x1={startTopX}
        y1={startTopY}
        x2={startBottomX}
        y2={startBottomY}
        strokeWidth={props.strokeWidth}
        style={style} />
      <line
        x1={props.xStart}
        y1={props.yStart}
        x2={props.xEnd}
        y2={props.yEnd}
        strokeWidth={props.strokeWidth}
        style={style} />
      <line
        x1={endTopX}
        y1={endTopY}
        x2={endBottomX}
        y2={endBottomY}
        strokeWidth={props.strokeWidth}
        style={style} />
      <text
        x={(props.xStart + props.xEnd) / 2}
        y={(props.yStart + props.yEnd) / 2}
        style={{
          transform: `rotate(${rotation}turn) scale(${1 / scale}) translateX(-50%) translateY(-100%)`,
          transformBox: 'fill-box'
        }}
      >
        {props.text}
      </text>
    </g>
  );
}
