"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImagePaste = void 0;
const base64_arraybuffer_1 = require("base64-arraybuffer");
const prosemirror_model_1 = require("prosemirror-model");
const prosemirror_state_1 = require("prosemirror-state");
const prosemirror_transform_1 = require("prosemirror-transform");
const input_state_1 = require("../../../../utils/input-state.js");
const core_1 = require("../../../../core/index.js");
const lodash_1 = require("../../../../lodash.js");
const Clipboard_1 = require("../../../behavior/Clipboard/index.js");
const utils_1 = require("../../../behavior/Clipboard/utils.js");
const specs_1 = require("../../../specs.js");
const utils_2 = require("../utils.js");
const upload_1 = require("./upload.js");
const { isFilesFromHtml, isFilesOnly, isImageFile } = Clipboard_1.clipboardUtils;
const ImagePaste = (builder, opts) => {
    const { parseInsertedUrlAsImage, imageUploadHandler } = opts ?? {};
    if (!(0, lodash_1.isFunction)(imageUploadHandler ?? parseInsertedUrlAsImage))
        throw new Error(`ImagePaste extension: ${opts.imageUploadHandler ? 'imageUploadHandler' : 'parseInsertedUrlAsImage'} is not a function`);
    const inputState = new input_state_1.InputState();
    builder.addPlugin(() => new prosemirror_state_1.Plugin({
        props: {
            handleDOMEvents: {
                keydown(_view, e) {
                    inputState.keydown(e);
                },
                keyup(_view, e) {
                    inputState.keyup(e);
                },
                paste(view, e) {
                    const logger = (0, core_1.getLoggerFromState)(view.state).nested({
                        plugin: 'image-paste',
                        domEvent: 'paste',
                    });
                    const files = getPastedImages(e.clipboardData);
                    if (imageUploadHandler && files) {
                        e.preventDefault();
                        logger.event({ event: 'paste-images' });
                        new upload_1.ImagesUploadProcess(view, files, imageUploadHandler, view.state.tr.selection.from, opts).run();
                        return true;
                    }
                    else if (!inputState.shiftKey && parseInsertedUrlAsImage) {
                        const { imageUrl, title } = parseInsertedUrlAsImage(e.clipboardData?.getData(utils_1.DataTransferType.Text) ?? '') || {};
                        if (!imageUrl) {
                            return false;
                        }
                        e.preventDefault();
                        const imageNode = (0, specs_1.imageType)(view.state.schema).create({
                            src: imageUrl,
                            alt: title,
                        });
                        const tr = view.state.tr.replaceSelectionWith(imageNode);
                        view.dispatch(tr.scrollIntoView());
                        logger.event({ event: 'paste-url-as-image' });
                        return true;
                    }
                    return false;
                },
                drop(view, e) {
                    if (!imageUploadHandler) {
                        return false;
                    }
                    // handle drop images from device
                    if (view.dragging)
                        return false;
                    const files = getPastedImages(e.dataTransfer);
                    if (!files)
                        return false;
                    const dropPos = view.posAtCoords({ left: e.clientX, top: e.clientY })?.pos ?? -1;
                    if (dropPos === -1)
                        return false;
                    const posToInsert = (0, prosemirror_transform_1.dropPoint)(view.state.doc, dropPos, createFakeImageSlice(view.state.schema));
                    const logger = (0, core_1.getLoggerFromState)(view.state);
                    logger.event({
                        event: 'drop-image',
                        plugin: 'image-paste',
                        domEvent: 'drop',
                        runProcess: posToInsert !== null,
                    });
                    if (posToInsert !== null) {
                        new upload_1.ImagesUploadProcess(view, files, imageUploadHandler, posToInsert, opts).run();
                    }
                    e.preventDefault();
                    return true;
                },
            },
            handlePaste(view, _event, slice) {
                if (!imageUploadHandler) {
                    return false;
                }
                const node = sliceSingleNode(slice);
                if (node && (0, utils_2.isImageNode)(node)) {
                    const imgUrl = node.attrs[specs_1.ImgSizeAttr.Src];
                    const imgFile = dataUrlToFile(imgUrl, 'image');
                    if (imgFile) {
                        new upload_1.ImagesUploadProcess(view, [imgFile], imageUploadHandler, view.state.tr.selection.from, opts).run();
                        return true;
                    }
                }
                return false;
            },
        },
    }), builder.Priority.VeryHigh);
};
exports.ImagePaste = ImagePaste;
function getPastedImages(data) {
    if (!data || data.files.length === 0)
        return null;
    if (!isFilesOnly(data) && !isFilesFromHtml(data))
        return null;
    const files = Array.from(data.files);
    return files.every(isImageFile) ? files : null;
}
function createFakeImageSlice(schema) {
    return new prosemirror_model_1.Slice(prosemirror_model_1.Fragment.from((0, specs_1.imageType)(schema).create({
        [specs_1.ImageAttr.Src]: 'fake',
        [specs_1.ImageAttr.Title]: 'image',
    })), 0, 0);
}
// copied from prosemirror-view input.ts
function sliceSingleNode(slice) {
    return slice.openStart === 0 && slice.openEnd === 0 && slice.content.childCount === 1
        ? slice.content.firstChild
        : null;
}
function dataUrlToFile(dataUrl, filename) {
    const [data, base64String] = dataUrl.split(',');
    if (!data || !base64String)
        return null;
    const mime = data.match(/^data:(.+);base64/)?.[1];
    if (!mime)
        return null;
    return new File([(0, base64_arraybuffer_1.decode)(base64String)], filename, { type: mime });
}
//# sourceMappingURL=index.js.map
