import { useCallback, useEffect, useRef, useState } from 'react';

export type Modifiers = {
  ctrl: boolean;
  shift: boolean;
  alt: boolean;
};

const useModifierKeys = (asReactState?: boolean) => {
  const modifiersRef = useRef<Modifiers>({
    ctrl: false,
    shift: false,
    alt: false,
  });
  const [modifiersState, setModifiersState] = useState<Modifiers>({
    ctrl: false,
    shift: false,
    alt: false,
  });
  const setModifierKeys = useCallback(
    (e: KeyboardEvent, down: boolean) => {
      if (e.key === 'Control' || e.key === 'Meta') {
        modifiersRef.current.ctrl = down;
        if (asReactState) setModifiersState({ ...modifiersRef.current });
      } else if (e.key === 'Shift') {
        modifiersRef.current.shift = down;
        if (asReactState) setModifiersState({ ...modifiersRef.current });
      } else if (e.key === 'Alt') {
        modifiersRef.current.alt = down;
        if (asReactState) setModifiersState({ ...modifiersRef.current });
      }
    },
    [asReactState]
  );
  useEffect(() => {
    const onDown = (e: any) => setModifierKeys(e, true);
    const onUp = (e: any) => setModifierKeys(e, false);
    const onFocus = () => {
      modifiersRef.current.ctrl = false;
      modifiersRef.current.shift = false;
      modifiersRef.current.alt = false;
      if (asReactState) setModifiersState({ ...modifiersRef.current });
    };
    window.addEventListener('keydown', onDown);
    window.addEventListener('keyup', onUp);
    window.addEventListener('focus', onFocus);
    return () => {
      window.removeEventListener('keydown', onDown);
      window.removeEventListener('keyup', onUp);
      window.removeEventListener('focus', onFocus);
    };
  }, [setModifierKeys]);
  return asReactState ? modifiersState : modifiersRef.current;
};
export default useModifierKeys;
