import { mergeAttributes, Node } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import { CalloutComponent } from './callout-component'

export interface CalloutOptions {
    HTMLAttributes: Record<string, unknown>
}

declare module '@tiptap/core' {
    interface Commands<ReturnType> {
        callout: {
            setCallout: () => ReturnType
            toggleCallout: () => ReturnType
            unsetCallout: () => ReturnType
        }
    }
}

export const Callout = Node.create<CalloutOptions>({
    name: 'callout',

    group: 'block',

    content: 'block+',

    draggable: true,

    addOptions() {
        return {
            HTMLAttributes: {},
        }
    },

    addAttributes() {
        return {
            type: {
                default: 'info',
                parseHTML: element => element.getAttribute('data-type'),
                renderHTML: attributes => {
                    return { 'data-type': attributes.type }
                },
            },
        }
    },

    parseHTML() {
        return [
            {
                tag: 'div[data-type="callout"]',
            },
            // Backwards compatibility or paste handling could go here
            {
                tag: 'div[class^="callout-"]',
            }
        ]
    },

    renderHTML({ HTMLAttributes }) {
        return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { 'data-type': 'callout' }), 0]
    },

    addNodeView() {
        return ReactNodeViewRenderer(CalloutComponent)
    },

    addCommands() {
        return {
            setCallout:
                () =>
                    ({ commands }) => {
                        return commands.wrapIn(this.name)
                    },
            toggleCallout:
                () =>
                    ({ commands }) => {
                        return commands.toggleWrap(this.name)
                    },
            unsetCallout:
                () =>
                    ({ commands }) => {
                        return commands.lift(this.name)
                    },
        }
    },
})
