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

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> = ({
  id,
  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.key === 'Delete') {
      deleteDialogToggle();
    }
  };

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

  const childProps = {
    id,
    obj_type,
    obj_attr,
    scale,
    isCollapse,
    isCovered,
    mousePosition,
    onUpdate: handleUpdate,
    onDelete: deleteDialogToggle,
    viewport,
    onEdit: handleEdit,
    isEdit,
    onBlur: handleInputBlur,
  };

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

  return (
    <AnnotationWrapper ref={ref} {...wrapperProps}>
      {((): React.ReactNode => {
        switch (obj_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} />;
        }
      })()}
      {openDialog && (
        <DeleteDialog onCancel={deleteDialogToggle} onDelete={handleDelete} />
      )}
    </AnnotationWrapper>
  );
};

export default Annotation;
