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

import hotkeys from 'hotkeys-js';

let KeyScopeContext = React.createContext('app');

hotkeys.filter = event => {
  var target = event.target || event.srcElement;
  var tagName = target.tagName;

  // This is the default behavior of hotkeys, except we only suppress
  // key presses if the meta key is not pressed
  if (
    !event.metaKey &&
    (target.isContentEditable ||
      ((tagName === 'INPUT' ||
        tagName === 'TEXTAREA' ||
        tagName === 'SELECT') &&
        !target.readOnly))
  ) {
    return false;
  }

  return true;
};

export function KeyHandler({ keyName, eventType = 'keydown', handler }) {
  let scope = useContext(KeyScopeContext);

  if (eventType !== 'keyup' && eventType !== 'keydown') {
    throw new Error('KeyHandler: unknown event type: ' + eventType);
  }

  useEffect(() => {
    function _handler(event, hk) {
      // Right now it always overrides the default behavior, but in
      // the future we can make this customizable
      event.preventDefault();

      if (event.type === eventType && handler) {
        return handler(event, hk);
      }
    }
    hotkeys(keyName, { scope, keyup: true }, _handler);

    return () => {
      hotkeys.unbind({
        key: keyName,
        scope,
        method: _handler
      });
    };
  }, [keyName, handler, scope]);

  return null;
}

export function KeyHandlers({ eventType, keys = {} }) {
  let handlers = Object.keys(keys).map(key => {
    return (
      <KeyHandler
        key={key}
        keyName={key}
        eventType={eventType}
        handler={keys[key]}
      />
    );
  });

  return handlers;
}