import { useState, useEffect, MutableRefObject } from 'react';
import { ClientXAndClientY, IResizeOptions } from '../types';
import { useMiddlewareContext } from './useMiddlewareContext';

const cursor = {
  both: 'nwse-resize',
  vertical: 'ns-resize',
  horizontal: 'ew-resize',
};

export const useResize = (
  ref: MutableRefObject<HTMLDivElement>,
  options: IResizeOptions
) => {
  const { step = 1, axis = 'both' } = options || {};
  const [coords, setCoords] = useState({ x: Infinity, y: Infinity });
  const [dims, setDims] = useState({ width: Infinity, height: Infinity });
  const [size, setSize] = useState({ width: Infinity, height: Infinity });

  const { setIsResizing } = useMiddlewareContext();

  const initResize = <T extends ClientXAndClientY>(event: T) => {
    if (!ref.current) return;
    setCoords({ x: event.clientX, y: event.clientY });
    const { width, height } = window.getComputedStyle(ref.current);
    setDims({ width: parseInt(width, 10), height: parseInt(height, 10) });

    setIsResizing(true);
  };

  useEffect(() => {
    // Round the size based to `props.step`.
    const getValue = (input: number) => Math.ceil(input / step) * step;

    const doDrag = <T extends ClientXAndClientY>(event: T) => {
      if (!ref.current) return;

      // Calculate the box size.
      const width = getValue(dims.width + event.clientX - coords.x);
      const height = getValue(dims.height + event.clientY - coords.y);

      // Set the box size.
      if (axis === 'both') {
        ref.current.style.width = width + 'px';
        ref.current.style.height = height + 'px';
      }
      if (axis === 'horizontal') ref.current.style.width = width + 'px';
      if (axis === 'vertical') ref.current.style.height = height + 'px';
      setSize({ width, height });
    };

    const stopDrag = () => {
      document.removeEventListener('mousemove', doDrag, false);
      document.removeEventListener('mouseup', stopDrag, false);
      setIsResizing(false);
    };

    document.addEventListener('mousemove', doDrag, false);
    document.addEventListener('mouseup', stopDrag, false);
  }, [dims, coords, step, ref, axis]);

  return { initResize, size, cursor: cursor[axis] };
};
