import { useMemo } from 'react';
import { useTheme } from '@mui/material/styles';
import FileHandler from '@tiptap/extension-file-handler';
import Highlight from '@tiptap/extension-highlight';
import { TableKit } from '@tiptap/extension-table';
import TextAlign from '@tiptap/extension-text-align';
import { TextStyleKit } from '@tiptap/extension-text-style';
import { CharacterCount, Placeholder } from '@tiptap/extensions';
import { Plugin, PluginKey } from '@tiptap/pm/state';
import { Extension } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import { isFileToPaste } from '../../../../../utils/attachments';
import FontSize from '../extensions/fontSize';
import Iframe from '../extensions/iframe';
import ImageLoader from '../extensions/imageLoader';
import Indent from '../extensions/indent';
import RawHTML from '../extensions/rawHTML';
import ResizableInlineMedia from '../extensions/resizableMedia';
import VariablePill from '../extensions/variablePill';
import Video from '../extensions/video';
import { handleImageDrop, handleVideoDrop, isActiveLoader } from '../utils';
export const EventHandler = Extension.create({
    name: 'eventHandler',
    addOptions() {
        return {
            handlePaste: null,
        };
    },
    addProseMirrorPlugins() {
        const { handlePaste } = this.options;
        return [
            new Plugin({
                key: new PluginKey('eventHandler'),
                props: {
                    handlePaste(_, event) {
                        if (!isFileToPaste(event))
                            return false;
                        if (!handlePaste)
                            return false;
                        return handlePaste(event);
                    },
                },
            }),
        ];
    },
});
/**
 * Removes `image-loader` nodes whose id is not in the active-loader registry
 * (see `utils/loaderRegistry.ts`) — e.g. a loader resurrected by undo after
 * its upload already settled. Marked `addToHistory: false` so the cleanup
 * itself is not an undo target.
 */
const OrphanLoaderCleaner = Extension.create({
    name: 'orphanLoaderCleaner',
    addProseMirrorPlugins() {
        return [
            new Plugin({
                key: new PluginKey('orphanLoaderCleaner'),
                appendTransaction(_transactions, oldState, newState) {
                    if (oldState.doc === newState.doc)
                        return null;
                    const orphans = [];
                    newState.doc.descendants((node, pos) => {
                        if (node.type.name !== 'image-loader')
                            return;
                        const id = node.attrs.imageLoaderId;
                        if (isActiveLoader(id))
                            return;
                        orphans.push({ pos, size: node.nodeSize });
                    });
                    if (orphans.length === 0)
                        return null;
                    const tr = newState.tr;
                    for (let i = orphans.length - 1; i >= 0; i--) {
                        const { pos, size } = orphans[i];
                        tr.delete(pos, pos + size);
                    }
                    tr.setMeta('addToHistory', false);
                    return tr;
                },
            }),
        ];
    },
});
const DEFAULT_CHARACTER_LIMIT = 10000;
const useExtensions = ({ placeholder, handlePaste, slotProps, variablesEnabled = false, characterLimit = DEFAULT_CHARACTER_LIMIT, } = {}) => {
    const theme = useTheme();
    const uploadImageFunction = slotProps?.insertImage?.uploaderProps?.uploadFunction;
    const uploadVideoFunction = slotProps?.uploadVideo?.uploaderProps?.uploadFunction;
    return useMemo(() => {
        return [
            StarterKit.configure({
                horizontalRule: false,
                undoRedo: {
                    depth: 1,
                },
                heading: {
                    levels: [1, 2, 3, 4],
                },
                link: {
                    openOnClick: false,
                    autolink: true,
                    linkOnPaste: true,
                    defaultProtocol: 'https',
                },
                dropcursor: {
                    color: theme.palette.new.action.button.background.primary.default,
                    width: 4,
                },
            }),
            CharacterCount.configure({
                limit: characterLimit,
            }),
            Placeholder.configure({
                placeholder,
            }),
            TextAlign.configure({
                types: [
                    'heading',
                    'paragraph',
                    'div',
                    'resizable-media',
                    'raw-html',
                    'tableCell',
                ],
            }),
            Indent.configure({
                margin: 20,
            }),
            TextStyleKit.configure({
                // Disable the built-in FontSize so we can register our custom one,
                // which also propagates the font size to list items so that the
                // `<li>` marker (bullet/number) scales with the text.
                fontSize: false,
            }),
            FontSize,
            Highlight.configure({
                multicolor: true,
            }),
            Video,
            Iframe,
            TableKit.configure({
                table: {
                    resizable: true,
                    renderWrapper: true,
                },
            }),
            EventHandler.configure({
                handlePaste, // Pass the handlePaste function to the EventHandler
            }),
            OrphanLoaderCleaner,
            ResizableInlineMedia,
            ImageLoader,
            RawHTML,
            FileHandler.configure({
                allowedMimeTypes: [
                    'image/png',
                    'image/jpeg',
                    'image/gif',
                    'image/webp',
                    'video/mp4',
                    'video/webm',
                    'video/ogg',
                    'video/quicktime',
                    'video/mov',
                ],
                onDrop: async (currentEditor, files, pos) => {
                    const images = files.filter(file => file.type.includes('image'));
                    const videos = files.filter(file => file.type.includes('video'));
                    let currentPos = pos;
                    if (images.length > 0) {
                        await handleImageDrop(currentEditor, images, currentPos, {
                            uploadImageFunction,
                        });
                        currentPos += images.length;
                    }
                    if (videos.length > 0) {
                        await handleVideoDrop(currentEditor, videos, currentPos, {
                            uploadVideoFunction,
                        });
                    }
                },
                onPaste: async (currentEditor, files, htmlContent) => {
                    if (htmlContent && files.length === 0) {
                        return false;
                    }
                    const images = files.filter(file => file.type.includes('image'));
                    const videos = files.filter(file => file.type.includes('video'));
                    const pos = currentEditor.state.selection.anchor;
                    let currentPos = pos;
                    if (images.length > 0) {
                        await handleImageDrop(currentEditor, images, currentPos, {
                            uploadImageFunction,
                        });
                        currentPos += images.length;
                    }
                    if (videos.length > 0) {
                        await handleVideoDrop(currentEditor, videos, currentPos, {
                            uploadVideoFunction,
                        });
                    }
                },
            }),
            // TODO: Add in the future.
            // Mention.configure({
            //   HTMLAttributes: {
            //     class: 'mention',
            //   },
            //   suggestion: mentionOptions,
            //   renderHTML({ options, node }) {
            //     return [
            //       'a',
            //       mergeAttributes(
            //         {
            //           href: getProfileDetailHref(node.attrs.id),
            //         },
            //         options.HTMLAttributes,
            //       ),
            //       `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`,
            //     ];
            //   },
            // }),
            ...(variablesEnabled ? [VariablePill] : []),
        ];
    }, [
        placeholder,
        handlePaste,
        theme.palette.new.action.button.background.primary.default,
        uploadImageFunction,
        uploadVideoFunction,
        variablesEnabled,
        characterLimit,
    ]);
};
export default useExtensions;
