window.WebpImagePaster = window.WebpImagePaster || {};

window.WebpImagePaster.Editor = (function () {
    var Utils = window.WebpImagePaster.Utils;
    var __ = wp.i18n.__;

    var savedInsertionIndex = undefined;
    var savedRootClientId = undefined;
    var savedReplaceClientId = undefined;

    var isMediaModalRealtimeOpen = false;
    var isDragSessionLocked = false;

    function initMediaObserver() {
        try {
            var targetDoc = document;
            if (window.top && window.top.document) {
                targetDoc = window.top.document;
            }

            var observer = new MutationObserver(function () {
                var modalOpen = false;
                if (targetDoc.body && targetDoc.body.classList) {
                    modalOpen = targetDoc.body.classList.contains('modal-open');
                }
                isMediaModalRealtimeOpen = modalOpen;
            });

            if (targetDoc.body) {
                observer.observe(targetDoc.body, { attributes: true, attributeFilter: ['class'] });
            }
        } catch (e) {
            // 권한 예외 무시
        }
    }
    initMediaObserver();

    function isMediaModalActive(event) {
        if (isMediaModalRealtimeOpen || isDragSessionLocked) {
            return true;
        }
        if (event && event.target && event.target.closest) {
            if (event.target.closest('.media-modal, .uploader-window')) {
                return true;
            }
        }
        return false;
    }

    function isFeaturedImageDropTarget(event) {
        if (!event) {
            return false;
        }

        var selectors = [
            '.editor-post-featured-image',
            '.editor-post-featured-image__container',
            '.editor-post-featured-image__preview',
            '.editor-post-featured-image__toggle',
            '.edit-post-post-featured-image',
            '[class*="editor-post-featured-image"]',
            '[data-type="core/post-featured-image"]'
        ].join(', ');

        if (event.target && event.target.closest && event.target.closest(selectors)) {
            return true;
        }

        if (typeof event.clientX === 'number' && typeof event.clientY === 'number') {
            var doc = (event.target && event.target.ownerDocument) ? event.target.ownerDocument : document;
            var elFromPoint = doc.elementFromPoint(event.clientX, event.clientY);
            if (elFromPoint && elFromPoint.closest && elFromPoint.closest(selectors)) {
                return true;
            }
        }

        return false;
    }

    function getDroppedBlockClientId(event) {
        var target = event.target;
        var el = null;

        if (target && target.closest) {
            el = target.closest('[data-block]') || target.closest('[id^="block-"]');
        }

        if (!el && typeof event.clientX === 'number' && typeof event.clientY === 'number') {
            var doc = (event.target && event.target.ownerDocument) ? event.target.ownerDocument : document;
            var elFromPoint = doc.elementFromPoint(event.clientX, event.clientY);
            if (elFromPoint && elFromPoint.closest) {
                el = elFromPoint.closest('[data-block]') || elFromPoint.closest('[id^="block-"]');
            }
        }

        if (el) {
            var cId = el.getAttribute('data-block');
            if (!cId && el.id && el.id.indexOf('block-') === 0) {
                cId = el.id.replace('block-', '');
            }
            return cId;
        }
        return null;
    }

    function attachPasteListeners(onImageDropOrPaste) {
        function handleDragEnter(event) {
            if (isMediaModalRealtimeOpen || isMediaModalActive(event)) {
                isDragSessionLocked = true;
            }
        }

        function handleDragLeave(event) {
            if (event.clientX === 0 && event.clientY === 0) {
                isDragSessionLocked = false;
            }
        }

        function handlePasteEvent(event) {
            if (isMediaModalActive(event)) {
                return;
            }

            var items = event && event.clipboardData ? event.clipboardData.items : null;
            var cbFiles = event && event.clipboardData ? event.clipboardData.files : null;
            var imageBlobs = [];

            if (items && items.length > 0) {
                for (var i = 0; i < items.length; i++) {
                    var item = items[i];
                    if (item.type && item.type.indexOf('image') !== -1) {
                        var file = item.getAsFile();
                        if (file) {
                            imageBlobs.push(file);
                        }
                    }
                }
            }

            if (imageBlobs.length === 0 && cbFiles && cbFiles.length > 0) {
                for (var f = 0; f < cbFiles.length; f++) {
                    var cbFile = cbFiles[f];
                    if (Utils.isImageFile ? Utils.isImageFile(cbFile) : (cbFile.type && cbFile.type.indexOf('image') !== -1)) {
                        imageBlobs.push(cbFile);
                    }
                }
            }

            if (imageBlobs.length === 0) {
                return;
            }

            event.preventDefault();
            event.stopImmediatePropagation();

            if (wp && wp.data && wp.data.select && wp.data.select('core/block-editor')) {
                var blockEditor = wp.data.select('core/block-editor');
                var insertionPoint = blockEditor.getBlockInsertionPoint();
                if (insertionPoint) {
                    savedInsertionIndex = insertionPoint.index;
                    savedRootClientId = insertionPoint.rootClientId;
                }
                savedReplaceClientId = undefined;

                var selectedClientId = blockEditor.getSelectedBlockClientId();
                if (selectedClientId) {
                    var selectedBlock = blockEditor.getBlock(selectedClientId);
                    if (selectedBlock) {
                        if (selectedBlock.name === 'core/paragraph') {
                            var pContent = selectedBlock.attributes ? selectedBlock.attributes.content : '';
                            if (!pContent || Utils.sanitizeAltText(pContent).trim() === '') {
                                savedReplaceClientId = selectedClientId;
                            }
                        } else if (selectedBlock.name === 'core/image') {
                            savedReplaceClientId = selectedClientId;
                        }
                    }
                }
            }

            onImageDropOrPaste(imageBlobs);
        }

        function handleDragOver(event) {
            if (isMediaModalActive(event)) {
                return;
            }

            if (event && event.dataTransfer && event.dataTransfer.types) {
                var types = event.dataTransfer.types;
                for (var i = 0; i < types.length; i++) {
                    if (types[i] === 'Files') {
                        event.preventDefault();
                        break;
                    }
                }
            }
        }

        function handleDropEvent(event) {
            var wasLocked = isDragSessionLocked;
            isDragSessionLocked = false;

            if (wasLocked || isMediaModalActive(event)) {
                return;
            }

            if (event && event.target && event.target.closest && event.target.closest('.media-modal')) {
                return;
            }

            var files = event && event.dataTransfer ? event.dataTransfer.files : null;
            if (!files || files.length === 0) {
                return;
            }

            var imageFiles = [];
            for (var fIdx = 0; fIdx < files.length; fIdx++) {
                var file = files[fIdx];
                if (Utils.isImageFile ? Utils.isImageFile(file) : (file.type && file.type.indexOf('image') !== -1)) {
                    imageFiles.push(file);
                }
            }

            if (imageFiles.length === 0) {
                return;
            }

            event.preventDefault();
            event.stopImmediatePropagation();

            var isFeatured = isFeaturedImageDropTarget(event);
            var targetMode = isFeatured ? 'featured_image' : 'content';

            if (!isFeatured && wp && wp.data && wp.data.select && wp.data.select('core/block-editor')) {
                var blockEditor = wp.data.select('core/block-editor');
                savedReplaceClientId = undefined;

                // 1. 마우스가 떨어진 대상 블록 확인
                var droppedClientId = getDroppedBlockClientId(event);
                if (droppedClientId) {
                    var droppedBlock = blockEditor.getBlock(droppedClientId);
                    if (droppedBlock) {
                        if (droppedBlock.name === 'core/image') {
                            savedReplaceClientId = droppedClientId;
                        } else if (droppedBlock.name === 'core/paragraph') {
                            var pText = droppedBlock.attributes ? droppedBlock.attributes.content : '';
                            if (!pText || Utils.sanitizeAltText(pText).trim() === '') {
                                savedReplaceClientId = droppedClientId;
                            }
                        }
                    }
                }

                // 2. 일반 위치 삽입 위치 수합
                var insertionPoint = blockEditor.getBlockInsertionPoint();
                if (insertionPoint) {
                    savedInsertionIndex = insertionPoint.index;
                    savedRootClientId = insertionPoint.rootClientId;
                }

                // 3. 삽입 지점이 빈 문단 블록인 경우 교체 처리
                if (!savedReplaceClientId) {
                    var rootOrder = blockEditor.getBlockOrder(savedRootClientId);
                    if (rootOrder && typeof savedInsertionIndex === 'number') {
                        var targetClientId = rootOrder[savedInsertionIndex];
                        if (targetClientId) {
                            var targetBlock = blockEditor.getBlock(targetClientId);
                            if (targetBlock && targetBlock.name === 'core/paragraph') {
                                var content = targetBlock.attributes ? targetBlock.attributes.content : '';
                                if (!content || Utils.sanitizeAltText(content).trim() === '') {
                                    savedReplaceClientId = targetClientId;
                                }
                            }
                        }
                    }
                }
            } else {
                savedReplaceClientId = undefined;
                savedInsertionIndex = undefined;
                savedRootClientId = undefined;
            }

            onImageDropOrPaste(imageFiles, targetMode);
        }

        function attach() {
            window.addEventListener('paste', handlePasteEvent, true);
            document.addEventListener('paste', handlePasteEvent, true);

            window.addEventListener('dragenter', handleDragEnter, true);
            document.addEventListener('dragenter', handleDragEnter, true);
            window.addEventListener('dragleave', handleDragLeave, true);
            document.addEventListener('dragleave', handleDragLeave, true);

            window.addEventListener('dragover', handleDragOver, false);
            document.addEventListener('dragover', handleDragOver, false);

            window.addEventListener('drop', handleDropEvent, true);
            document.addEventListener('drop', handleDropEvent, true);

            var iframes = document.getElementsByTagName('iframe');
            for (var i = 0; i < iframes.length; i++) {
                var iframe = iframes[i];
                try {
                    if (iframe.contentWindow) {
                        iframe.contentWindow.addEventListener('paste', handlePasteEvent, true);
                        iframe.contentWindow.addEventListener('dragover', handleDragOver, false);
                        iframe.contentWindow.addEventListener('drop', handleDropEvent, true);
                    }
                    if (iframe.contentDocument) {
                        iframe.contentDocument.addEventListener('paste', handlePasteEvent, true);
                        iframe.contentDocument.addEventListener('dragover', handleDragOver, false);
                        iframe.contentDocument.addEventListener('drop', handleDropEvent, true);
                    }
                } catch (e) {
                    // CORS 예외 무시
                }
            }
        }

        attach();
        var timer = setTimeout(attach, 1500);

        return function cleanup() {
            clearTimeout(timer);
            window.removeEventListener('paste', handlePasteEvent, true);
            document.removeEventListener('paste', handlePasteEvent, true);
            window.removeEventListener('dragenter', handleDragEnter, true);
            document.removeEventListener('dragenter', handleDragEnter, true);
            window.removeEventListener('dragleave', handleDragLeave, true);
            document.removeEventListener('dragleave', handleDragLeave, true);
            window.removeEventListener('dragover', handleDragOver, false);
            document.removeEventListener('dragover', handleDragOver, false);
            window.removeEventListener('drop', handleDropEvent, true);
            document.removeEventListener('drop', handleDropEvent, true);
        };
    }

    function uploadAndInsert(blob, fileName, altText) {
        var formData = new FormData();
        formData.append('file', blob, fileName);
        if (altText) {
            formData.append('alt_text', altText);
        }

        return wp.apiFetch({
            path: '/wp/v2/media',
            method: 'POST',
            body: formData
        }).then(function (response) {
            if (response && response.source_url) {
                var block = wp.blocks.createBlock('core/image', {
                    url: response.source_url,
                    id: response.id,
                    alt: altText || ''
                });

                var blockEditorDispatch = wp.data.dispatch('core/block-editor');
                var blockEditorSelect = wp.data.select('core/block-editor');

                var replaced = false;
                if (savedReplaceClientId && blockEditorSelect) {
                    if (blockEditorSelect.getBlock(savedReplaceClientId)) {
                        blockEditorDispatch.replaceBlocks(savedReplaceClientId, block);
                        replaced = true;
                    }
                }

                if (!replaced && blockEditorDispatch) {
                    blockEditorDispatch.insertBlocks(block, savedInsertionIndex, savedRootClientId);
                }

                savedInsertionIndex = undefined;
                savedRootClientId = undefined;
                savedReplaceClientId = undefined;
            }
            return response;
        }).catch(function (error) {
            alert(__('Upload failed: ', 'webp-image-paster') + (error ? error.message : ''));
            throw error;
        });
    }

    function uploadAndInsertGallery(items, onProgress) {
        if (!items || items.length === 0) {
            return Promise.resolve();
        }

        var total = items.length;
        var completed = 0;

        function uploadItem(item) {
            var formData = new FormData();
            formData.append('file', item.blob, item.fileName);
            if (item.altText) {
                formData.append('alt_text', item.altText);
            }

            return wp.apiFetch({
                path: '/wp/v2/media',
                method: 'POST',
                body: formData
            }).then(function (res) {
                completed++;
                if (onProgress) {
                    onProgress(completed, total);
                }
                return { response: res, item: item };
            });
        }

        var uploadPromises = [];
        for (var i = 0; i < total; i++) {
            uploadPromises.push(uploadItem(items[i]));
        }

        return Promise.all(uploadPromises).then(function (results) {
            var innerImageBlocks = [];
            for (var rIdx = 0; rIdx < results.length; rIdx++) {
                var res = results[rIdx].response;
                var itm = results[rIdx].item;
                if (res && res.source_url) {
                    var imgBlock = wp.blocks.createBlock('core/image', {
                        url: res.source_url,
                        id: res.id,
                        alt: itm.altText || ''
                    });
                    innerImageBlocks.push(imgBlock);
                }
            }

            if (innerImageBlocks.length > 0) {
                var galleryBlock = wp.blocks.createBlock('core/gallery', {}, innerImageBlocks);
                var blockEditorDispatch = wp.data.dispatch('core/block-editor');
                var blockEditorSelect = wp.data.select('core/block-editor');

                var replaced = false;
                if (savedReplaceClientId && blockEditorSelect) {
                    if (blockEditorSelect.getBlock(savedReplaceClientId)) {
                        blockEditorDispatch.replaceBlocks(savedReplaceClientId, galleryBlock);
                        replaced = true;
                    }
                }

                if (!replaced && blockEditorDispatch) {
                    blockEditorDispatch.insertBlocks(galleryBlock, savedInsertionIndex, savedRootClientId);
                }
            }

            savedInsertionIndex = undefined;
            savedRootClientId = undefined;
            savedReplaceClientId = undefined;
        }).catch(function (error) {
            alert(__('Upload failed: ', 'webp-image-paster') + (error ? error.message : ''));
            throw error;
        });
    }

    function uploadAndSetFeaturedImage(blob, fileName, altText) {
        var formData = new FormData();
        formData.append('file', blob, fileName);
        if (altText) {
            formData.append('alt_text', altText);
        }

        return wp.apiFetch({
            path: '/wp/v2/media',
            method: 'POST',
            body: formData
        }).then(function (response) {
            if (response && response.id) {
                if (wp && wp.data && wp.data.dispatch && wp.data.dispatch('core/editor')) {
                    wp.data.dispatch('core/editor').editPost({ featured_media: response.id });
                }
            }
            return response;
        }).catch(function (error) {
            alert(__('Upload failed: ', 'webp-image-paster') + (error ? error.message : ''));
            throw error;
        });
    }

    return {
        initMediaObserver: initMediaObserver,
        isMediaModalActive: isMediaModalActive,
        isFeaturedImageDropTarget: isFeaturedImageDropTarget,
        attachPasteListeners: attachPasteListeners,
        uploadAndInsert: uploadAndInsert,
        uploadAndInsertGallery: uploadAndInsertGallery,
        uploadAndSetFeaturedImage: uploadAndSetFeaturedImage
    };
})();
