import React, { useEffect, useState, useCallback } from 'react';
import MobileDetect from 'mobile-detect';

import Icon from '../components/Icon';
import Button from '../components/Button';
import ExpansionPanel from '../components/ExpansionPanel';
import HighlightOption from '../components/HighlightOption';

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

import { getMarkupWithSelection } from '../helpers/markup';

type Props = {
  title: string;
  isActive: boolean;
  onClick: () => void;
};

let timer = 0;
let textLayer: HTMLElement | null = null;

const HighlightTools: React.FC<Props> = ({
  title,
  isActive,
  onClick,
}: Props) => {
  const [currentId, setCurrentId] = useState('');
  const [data, setData] = useState({
    type: 'highlight',
    color: '#FBB705',
    opacity: 35,
  });

  const [{ scale, annotations }, dispatch] = useStore();
  const { addAnnots, updateAnnots } = useActions(dispatch);

  const setDataState = (obj: OptionPropsType): void => {
    setData((prev) => ({
      ...prev,
      ...obj,
    }));
  };

  const handleDown = () => {
    timer = setTimeout(() => {
      setCurrentId('');
    }, 1500);
  };

  const handleMove = () => {
    if (timer) {
      clearTimeout(timer);
    }
  };

  const handleUp = useCallback(
    (e: MouseEvent | TouchEvent): void => {
      const selection = document.getSelection();

      if (!selection?.isCollapsed && !currentId) {
        if (e.target) {
          textLayer = (e.target as HTMLElement).parentNode as HTMLElement;

          if (textLayer.getAttribute('data-id') !== 'text-layer') {
            textLayer = textLayer.querySelector(
              '[data-id="text-layer"]',
            ) as HTMLElement;
          }
          if (textLayer) {
            textLayer.style.zIndex = '10';

            const newMarkup = getMarkupWithSelection({
              ...data,
              scale,
              textLayer,
            });

            if (newMarkup) {
              setCurrentId(newMarkup.id as string);
              addAnnots([newMarkup]);
            }
          }
        }
      }
      if (selection?.isCollapsed) {
        if (textLayer) {
          textLayer.style.zIndex = '0';
        }

        setCurrentId('');
      }
    },
    [data, scale, currentId],
  );

  const handleSelectStart = () => {
    setCurrentId('');
  };

  const handleSelectChange = useCallback(() => {
    const selection = document.getSelection();

    if (!selection?.isCollapsed && currentId) {
      if (textLayer) {
        const newMarkup = getMarkupWithSelection({
          ...data,
          scale,
          textLayer,
        });

        if (newMarkup) {
          const array: AnnotationType[] = [];
          annotations.forEach((ele) => {
            if (ele.id === currentId) {
              // eslint-disable-next-line no-param-reassign
              ele.obj_attr.position = newMarkup.obj_attr.position;
            }
            array.push(ele);
          });

          updateAnnots(array);
        }
      }
    }
  }, [annotations, data, scale, currentId]);

  useEffect(() => {
    const md = new MobileDetect(window.navigator.userAgent);

    if (isActive) {
      document.addEventListener('mousedown', handleDown);
      document.addEventListener('mousemove', handleMove);
      document.addEventListener('mouseup', handleUp);
      document.addEventListener('selectstart', handleSelectStart);
      if (md.mobile() || md.tablet()) {
        document.addEventListener('touchstart', handleDown);
        document.addEventListener('touchmove', handleMove);
        document.addEventListener('touchend', handleUp);
        document.addEventListener('selectionchange', handleSelectChange);
      }
    } else if (textLayer) {
      textLayer.style.zIndex = '0';
    }

    return (): void => {
      document.removeEventListener('mousedown', handleDown);
      document.removeEventListener('mousemove', handleMove);
      document.removeEventListener('mouseup', handleUp);
      document.removeEventListener('selectstart', handleSelectStart);
      if (md.mobile() || md.tablet()) {
        document.removeEventListener('touchstart', handleDown);
        document.removeEventListener('touchmove', handleMove);
        document.removeEventListener('touchend', handleUp);
        document.removeEventListener('selectionchange', handleSelectChange);
      }
    };
  }, [isActive, handleUp, handleSelectChange]);

  const Label = (
    <Button
      shouldFitContainer
      align="left"
      onClick={onClick}
      isActive={isActive}
    >
      <Icon glyph="highlight" style={{ marginRight: '10px' }} />
      {title}
    </Button>
  );

  return (
    <ExpansionPanel label={Label} isActive={isActive} showBottomBorder>
      <HighlightOption {...data} setDataState={setDataState} />
    </ExpansionPanel>
  );
};

export default HighlightTools;
