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 ClickAwayListener from '../components/ClickAwayListener';
import { appendUserIdAndDate } from '../helpers/annotation';

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;
    annotations[index] = appendUserIdAndDate(annotations[index]);
    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]);

  useEffect(() => {
    return () => {
      handleMouseOut();
      handleBlur();
      setEdit(false);
    };
  }, []);

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

  const wrapperProps = {
    onMouseDown: handleClick,
    onKeyDown: handleKeyDown,
  };

  return (
    <ClickAwayListener onClick={handleBlur}>
      <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>
    </ClickAwayListener>
  );
};

export default Annotation;
