import { Node, mergeAttributes } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react';
import { VariableChip } from './VariableChip';

export interface VariableNodeAttributes {
  path: string;
  label: string;
  type: string;
}

declare module '@tiptap/core' {
  interface Commands<ReturnType> {
    variableNode: {
      insertVariable: (attrs: VariableNodeAttributes) => ReturnType;
    };
  }
}

export const VariableNode = Node.create({
  name: 'variable',

  group: 'inline',
  inline: true,
  atom: true,
  selectable: true,
  draggable: false,

  addAttributes() {
    return {
      path: { default: '' },
      label: { default: '' },
      type: { default: 'string' },
    };
  },

  parseHTML() {
    return [
      {
        tag: 'span[data-variable]',
        getAttrs: (element) => {
          const el = element as HTMLElement;
          return {
            path: el.getAttribute('data-variable-path'),
            label: el.getAttribute('data-variable-label'),
            type: el.getAttribute('data-variable-type'),
          };
        },
      },
    ];
  },

  renderHTML({ node, HTMLAttributes }) {
    return [
      'span',
      mergeAttributes(HTMLAttributes, {
        'data-variable': '',
        'data-variable-path': node.attrs.path,
        'data-variable-label': node.attrs.label,
        'data-variable-type': node.attrs.type,
      }),
      `{{${node.attrs.path}}}`,
    ];
  },

  renderText({ node }) {
    return `{{${node.attrs.path}}}`;
  },

  addNodeView() {
    return ReactNodeViewRenderer(VariableChip);
  },

  addCommands() {
    return {
      insertVariable:
        (attrs: VariableNodeAttributes) =>
        ({ commands }) => {
          return commands.insertContent({
            type: this.name,
            attrs,
          });
        },
    };
  },
});
