import _ from 'lodash';

export const rectCalc = (
  position: PositionType,
  viewHeight: number,
  scale: number,
): HTMLCoordinateType => ({
  top: viewHeight - position.top * scale,
  left: position.left * scale,
  width: (position.right - position.left) * scale,
  height: (position.top - position.bottom) * scale,
});

export const getPosition = (
  type: string,
  element: HTMLElement,
): AnnotationPositionType => {
  const attributes = element.attributes as ElementAttributeType;

  switch (type) {
    case 'Ink': {
      const gestures: PointType[][] = [];
      const nodes: NodeListOf<ChildNode> = element.childNodes[1].childNodes;
      const nodeList = Array.prototype.slice.call(nodes);
      nodeList.forEach((ele: HTMLElement) => {
        if (ele.tagName === 'gesture') {
          const points: PointType[] = [];
          const gestureArray = (ele.innerHTML || ele.textContent || '').split(
            ';',
          );

          gestureArray.forEach((ele1: string) => {
            const pointArr = ele1.split(',');
            const point = {
              x: parseInt(pointArr[0], 10),
              y: parseInt(pointArr[1], 10),
            };
            points.push(point);
          });
          gestures.push(points);
        }
      });

      return gestures;
    }
    case 'Line': {
      const start = attributes.start.value.split(',');
      const end = attributes.end.value.split(',');
      return {
        start: {
          x: parseInt(start[0], 10),
          y: parseInt(start[1], 10),
        },
        end: {
          x: parseInt(end[0], 10),
          y: parseInt(end[1], 10),
        },
      };
    }
    case 'Square':
    case 'Circle': {
      const width = parseInt(attributes.width.value, 10);
      const rect = attributes.rect.value.split(',');
      return {
        left: parseInt(rect[0], 10) + width,
        bottom: parseInt(rect[1], 10) + width,
        right: parseInt(rect[2], 10) - width,
        top: parseInt(rect[3], 10) - width,
      };
    }
    case 'Text':
    case 'FreeText':
    case 'textfield':
    case 'checkbox': {
      const rect = attributes.rect.value.split(',');
      return {
        left: parseInt(rect[0], 10),
        bottom: parseInt(rect[1], 10),
        right: parseInt(rect[2], 10),
        top: parseInt(rect[3], 10),
      };
    }
    case 'Highlight':
    case 'Underline':
    case 'Squiggly':
    case 'StrikeOut': {
      let tempArray: string[][] = [];

      if (attributes.coords) {
        const coords = attributes.coords.value.split(',');
        tempArray = _.chunk(coords, 8);
      }

      const position = tempArray.map((ele: string[]) => ({
        left: parseInt(ele[0], 10),
        bottom: parseInt(ele[1], 10),
        right: parseInt(ele[2], 10),
        top: parseInt(ele[5], 10),
      }));

      return position;
    }
    default:
      return {
        left: 0,
        bottom: 0,
        right: 0,
        top: 0,
      };
  }
};

export const parsePositionForBackend = (
  type: string,
  position: AnnotationPositionType,
  pageHeight: number,
  scale: number,
): AnnotationPositionType => {
  switch (type) {
    case 'Highlight':
    case 'Underline':
    case 'Squiggly':
    case 'StrikeOut': {
      const positionArray = position as PositionType[];

      return positionArray.map((ele: PositionType) => ({
        left: ele.left / scale,
        bottom: (pageHeight - ele.bottom) / scale,
        right: ele.right / scale,
        top: (pageHeight - ele.top) / scale,
      }));
    }
    case 'Square':
    case 'Circle':
    case 'FreeText':
    case 'Text':
    case 'Image':
    case 'textfield':
    case 'checkbox': {
      const normalPosition = position as PositionType;

      return {
        left: normalPosition.left / scale,
        bottom: (pageHeight - normalPosition.bottom) / scale,
        right: normalPosition.right / scale,
        top: (pageHeight - normalPosition.top) / scale,
      };
    }
    case 'Line': {
      const { start, end } = position as LinePositionType;

      return {
        start: {
          x: start.x / scale,
          y: (pageHeight - start.y) / scale,
        },
        end: {
          x: end.x / scale,
          y: (pageHeight - end.y) / scale,
        },
      };
    }
    case 'Ink': {
      if (Array.isArray(position)) {
        const points = position as PointType[][];
        return [
          points[0].map((point) => ({
            x: point.x / scale,
            y: (pageHeight - point.y) / scale,
          })),
        ];
      }
      const point = position as PointType;
      return {
        x: point.x / scale,
        y: (pageHeight - point.y) / scale,
      };
    }
    default:
      return {
        left: 0,
        bottom: 0,
        right: 0,
        top: 0,
      };
  }
};

type GetAbsoluteCoordinateType = (
  parentElement: HTMLElement | SVGSVGElement | SVGCircleElement | null,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  clickEvent: any,
) => { x: number; y: number };

export const getAbsoluteCoordinate: GetAbsoluteCoordinateType = (
  parentElement,
  clickEvent,
) => {
  if (!parentElement) return { x: 0, y: 0 };

  let pageX = 0;
  let pageY = 0;
  if (clickEvent.touches) {
    const touch = clickEvent.touches[0];
    ({ pageX, pageY } = touch);
  } else {
    ({ pageX, pageY } = clickEvent);
  }

  const rect = parentElement.getBoundingClientRect();
  const offsetX = window.pageXOffset || window.scrollX || 0;
  const offsetY = window.pageYOffset || window.scrollY || 0;
  const coordinate = {
    x: pageX - rect.left - offsetX,
    y: pageY - rect.top - offsetY,
  };

  return coordinate;
};

export default rectCalc;
