import { mapValues, omit } from 'lodash';
import { InputRule } from 'prosemirror-inputrules';
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';
import Tracking from '~/tracking';
import {
  CONTENT_EDITOR_TRACKING_LABEL,
  KEYBOARD_SHORTCUT_TRACKING_ACTION,
  INPUT_RULE_TRACKING_ACTION,
} from '../constants';

const trackKeyboardShortcut = (contentType, commandFn, shortcut) => () => {
  Tracking.event(undefined, KEYBOARD_SHORTCUT_TRACKING_ACTION, {
    label: CONTENT_EDITOR_TRACKING_LABEL,
    property: `${contentType}.${shortcut}`,
  });
  return commandFn();
};

const trackInputRule = (contentType, inputRule) => {
  return new InputRule(inputRule.match, (...args) => {
    const result = inputRule.handler(...args);

    if (result) {
      Tracking.event(undefined, INPUT_RULE_TRACKING_ACTION, {
        label: CONTENT_EDITOR_TRACKING_LABEL,
        property: contentType,
      });
    }

    return result;
  });
};

const trackInputRulesAndShortcuts = (tiptapExtension) => {
  return tiptapExtension.extend({
    addKeyboardShortcuts() {
      const shortcuts = this.parent?.() || {};
      const { name } = this;

      /**
       * We don’t want to track keyboard shortcuts
       * that are not deliberately executed to create
       * new types of content
       */
      const withoutEnterShortcut = omit(shortcuts, [ENTER_KEY, BACKSPACE_KEY]);
      const decorated = mapValues(withoutEnterShortcut, (commandFn, shortcut) =>
        trackKeyboardShortcut(name, commandFn, shortcut),
      );

      return decorated;
    },
    addInputRules() {
      const inputRules = this.parent?.() || [];
      const { name } = this;

      return inputRules.map((inputRule) => trackInputRule(name, inputRule));
    },
  });
};

export default trackInputRulesAndShortcuts;
