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

import { AnnotationType, OnUpdateType } from '../constants/type';
import AnnotationWrapper from '../components/AnnotationWrapper';
import Highlight from '../components/Highlight';
import Ink from '../components/Ink';
import FreeText from '../components/FreeText';
import StickyNote from '../components/StickyNote';
import Shape from '../components/Shape';
import Line from '../components/Line';
import DeleteDialog from '../components/DeleteDialog';
import useCursorPosition from '../hooks/useCursorPosition';

import useStore from '../store';
import useActions from '../actions';

type Props = AnnotationType & {
  index: number;
  scale: number;
};

const Annotation: React.FC<Props> = ({
  obj_type,
  obj_attr,
  index,
  scale,
}: Props) => {
  const [isCollapse, setCollapse] = useState(true);
  const [isEdit, setEdit] = useState(false);
  const [isCovered, setMouseOver] = useState(false);
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
  const [openDialog, setDialog] = useState(false);
  const [cursorPosition, ref] = useCursorPosition();
  const [{ viewport, annotations }, dispatch] = useStore();
  const { updateAnnots } = useActions(dispatch);

  const handleClick = (): void => {
    if (isCollapse && !isEdit) {
      setCollapse(false);
      setMousePosition({
        x: cursorPosition.x || 0,
        y: cursorPosition.y || 0,
      });
    }
  };

  const handleMouseOver = (): void => {
    setMouseOver(true);
  };

  const handleMouseOut = (): void => {
    setMouseOver(false);
  };

  const handleUpdate: OnUpdateType = (data) => {
    const newAttributes = {
      ...annotations[index].obj_attr,
      ...data,
      isInit: false,
    };

    annotations[index].obj_attr = newAttributes;

    updateAnnots(annotations);
  };

  const handleEdit = (): void => {
    setEdit(true);
    setCollapse(true);
  };

  const deleteDialogToggle = (): void => {
    setDialog(!openDialog);
  };

  const handleDelete = (): void => {
    annotations.splice(index, 1);
    setDialog(false);
    updateAnnots(annotations);
  };

  const handleBlur = (): void => {
    setCollapse(true);
  };

  const handleInputBlur = (): void => {
    setEdit(false);

    if (obj_type === 'FreeText' && !obj_attr.content) {
      handleDelete();
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent): void => {
    if (e.keyCode === 46) {
      deleteDialogToggle();
    }
  };

  useEffect(() => {
    if (obj_type === 'FreeText' && !obj_attr.content) {
      setEdit(true);
    }
  }, [obj_type, obj_attr]);

  const Component = (type: string): React.ReactNode => {
    const childProps = {
      obj_type,
      obj_attr,
      scale,
      isCollapse,
      isCovered,
      mousePosition,
      onUpdate: handleUpdate,
      onDelete: deleteDialogToggle,
      viewport,
      onEdit: handleEdit,
      isEdit,
      onBlur: handleInputBlur,
    };

    switch (type) {
      case 'Ink':
        return <Ink {...childProps} />;
      case 'FreeText':
        return <FreeText {...childProps} />;
      case 'Text':
        return <StickyNote {...childProps} />;
      case 'Square':
      case 'Circle':
        return <Shape {...childProps} />;
      case 'Line':
      case 'Arrow':
        return <Line {...childProps} />;
      default:
        return <Highlight {...childProps} />;
    }
  };

  const wrapperProps = {
    onBlur: handleBlur,
    onMouseDown: handleClick,
    onMouseOver: handleMouseOver,
    onMouseOut: handleMouseOut,
    onKeyDown: handleKeyDown,
  };

  return (
    <AnnotationWrapper
      ref={ref}
      {...wrapperProps}
    >
      {Component(obj_type)}
      <DeleteDialog
        open={openDialog}
        onCancel={deleteDialogToggle}
        onDelete={handleDelete}
      />
    </AnnotationWrapper>
  );
};

export default Annotation;
