import { mapValues } from 'lodash';
import { InputRule } from '@tiptap/core';
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({
    find: inputRule.find,
    handler: (...args) => {
      const result = inputRule.handler(...args);

      if (result !== null) {
        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 dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY];
        const decorated = mapValues(shortcuts, (commandFn, shortcut) =>
          dotNotTrackKeys.includes(shortcut)
            ? commandFn
            : trackKeyboardShortcut(name, commandFn, shortcut),
        );

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

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

export default trackInputRulesAndShortcuts;
