(function (window, document) {
    'use strict';

    var EDITOR_FORMATS = [
        'header',
        'font',
        'size',
        'bold',
        'italic',
        'underline',
        'strike',
        'color',
        'background',
        'script',
        'list',
        'indent',
        'direction',
        'align',
        'blockquote',
        'code-block',
        'link',
        'image',
        'video',
    ];

    var DEFAULT_PICKER_LABELS = {
        font: {
            '': 'سانس',
            serif: 'سریف',
            monospace: 'تک‌فاصله',
        },
        size: {
            '': 'معمولی',
            small: 'کوچک',
            large: 'بزرگ',
            huge: 'بسیار بزرگ',
        },
        header: {
            '': 'معمولی',
            '1': 'عنوان ۱',
            '2': 'عنوان ۲',
            '3': 'عنوان ۳',
            '4': 'عنوان ۴',
            '5': 'عنوان ۵',
            '6': 'عنوان ۶',
        },
    };

    function readCfg() {
        return typeof window.zertiRichEditor === 'object' && window.zertiRichEditor !== null
            ? window.zertiRichEditor
            : {};
    }

    function pickerLabelMap(key) {
        var cfg = readCfg();
        var fromCfg = cfg.pickerLabels && cfg.pickerLabels[key];
        var defaults = DEFAULT_PICKER_LABELS[key] || {};
        if (!fromCfg || typeof fromCfg !== 'object') {
            return defaults;
        }
        var merged = {};
        Object.keys(defaults).forEach(function (k) {
            merged[k] = defaults[k];
        });
        Object.keys(fromCfg).forEach(function (k) {
            if (fromCfg[k]) {
                merged[k] = String(fromCfg[k]);
            }
        });
        return merged;
    }

    function labelForPickerValue(map, value) {
        if (!map) {
            return '';
        }
        var key = value === null || value === undefined ? '' : String(value);
        if (Object.prototype.hasOwnProperty.call(map, key)) {
            return map[key];
        }
        return map[''] || '';
    }

    function applyPickerLabels(wrap, pickerClass, map) {
        if (!map || !wrap) {
            return;
        }
        var picker = wrap.querySelector('.ql-picker.' + pickerClass);
        if (!picker) {
            return;
        }

        picker.querySelectorAll('.ql-picker-item').forEach(function (item) {
            var value = item.getAttribute('data-value');
            var label = labelForPickerValue(map, value);
            if (label) {
                item.setAttribute('data-label', label);
            }
        });

        var selected =
            picker.querySelector('.ql-picker-item.ql-selected') || picker.querySelector('.ql-picker-item');
        var labelEl = picker.querySelector('.ql-picker-label');
        if (selected && labelEl) {
            var selectedLabel = labelForPickerValue(map, selected.getAttribute('data-value'));
            if (selectedLabel) {
                labelEl.setAttribute('data-label', selectedLabel);
            }
        }
    }

    function applyToolbarPickerLabels(wrap) {
        applyPickerLabels(wrap, 'ql-font', pickerLabelMap('font'));
        applyPickerLabels(wrap, 'ql-size', pickerLabelMap('size'));
        applyPickerLabels(wrap, 'ql-header', pickerLabelMap('header'));

        var quill = wrap.__zertiQuill;
        if (quill && quill.theme && Array.isArray(quill.theme.pickers)) {
            quill.theme.pickers.forEach(function (picker) {
                if (picker && typeof picker.update === 'function') {
                    picker.update();
                }
            });
        }
    }

    function isEmptyHtml(html) {
        var trimmed = String(html || '')
            .replace(/\s/g, '')
            .toLowerCase();
        return trimmed === '' || trimmed === '<p><br></p>' || trimmed === '<p></p>';
    }

    function escapeAttr(str) {
        return String(str)
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
    }

    function syncEditor(wrap) {
        var textarea = wrap.querySelector('.zerti-rich-editor__source');
        var quill = wrap.__zertiQuill;
        if (!textarea || !quill) {
            return;
        }
        var html = quill.root.innerHTML;
        textarea.value = isEmptyHtml(html) ? '' : html;
    }

    function attachmentUrl(att) {
        if (!att) {
            return '';
        }
        if (att.url) {
            return String(att.url);
        }
        if (att.sizes && att.sizes.full && att.sizes.full.url) {
            return String(att.sizes.full.url);
        }
        if (att.sizes && att.sizes.large && att.sizes.large.url) {
            return String(att.sizes.large.url);
        }

        return '';
    }

    function isImageAttachment(att) {
        if (!att) {
            return false;
        }
        if (att.type === 'image') {
            return true;
        }
        var mime = String(att.mime || att.mime_type || '');
        return mime.indexOf('image/') === 0;
    }

    function insertHtmlAt(quill, html) {
        if (!html || typeof window.Quill !== 'function') {
            return;
        }
        var range = quill.getSelection(true);
        var index = range ? range.index : quill.getLength();
        var Delta = window.Quill.import('delta');
        var converted = quill.clipboard.convert({ html: html });
        quill.updateContents(new Delta().retain(index).concat(converted), 'user');
        quill.setSelection(index + converted.length(), 0);
    }

    function insertAttachment(quill, att) {
        var url = attachmentUrl(att);
        if (!url) {
            return;
        }

        if (isImageAttachment(att)) {
            var alt = att.alt || att.title || att.filename || '';
            var img =
                '<p><img src="' +
                escapeAttr(url) +
                '" alt="' +
                escapeAttr(alt) +
                '" loading="lazy" /></p>';
            insertHtmlAt(quill, img);
            return;
        }

        var label = att.title || att.filename || url;
        var linkHtml =
            '<p><a href="' +
            escapeAttr(url) +
            '" target="_blank" rel="noopener noreferrer">' +
            escapeAttr(label) +
            '</a></p>';
        insertHtmlAt(quill, linkHtml);
    }

    function buildToolbarConfig() {
        return {
            container: [
                ['bold', 'italic', 'underline', 'strike'],
                [{ script: 'sub' }, { script: 'super' }],
                [{ list: 'ordered' }, { list: 'bullet' }, { list: 'check' }],
                [{ indent: '-1' }, { indent: '+1' }],
                [{ direction: 'rtl' }],
                ['blockquote', 'code-block'],
                ['link', 'zertiMedia', 'video'],
                [{ color: [] }, { background: [] }],
                [{ align: [] }],
                ['clean'],
                [{ font: [] }, { size: ['small', false, 'large', 'huge'] }],
                [{ header: [1, 2, 3, 4, 5, 6, false] }],
            ],
            handlers: {
                zertiMedia: function () {
                    var editorWrap = this.quill.container.closest('[data-zerti-rich-editor]');
                    if (editorWrap) {
                        openWpMedia(editorWrap);
                    }
                },
            },
        };
    }

    function fixToolbarSvgViewBox(wrap) {
        wrap.querySelectorAll('.ql-toolbar svg[viewbox]').forEach(function (svg) {
            if (!svg.getAttribute('viewBox')) {
                svg.setAttribute('viewBox', svg.getAttribute('viewbox'));
            }
        });
    }

    function bindMediaToolbarButton(wrap) {
        var btn = wrap.querySelector('.ql-zertiMedia');
        if (!btn) {
            return;
        }
        var cfg = readCfg();
        var title = (cfg.i18n && cfg.i18n.mediaTitle) || '';
        btn.setAttribute('title', title);
        btn.setAttribute('aria-label', title);
    }

    function openWpMedia(wrap) {
        if (!window.wp || !window.wp.media) {
            return;
        }

        var quill = wrap.__zertiQuill;
        if (!quill) {
            return;
        }

        var cfg = readCfg();
        var frame = wrap.__zertiMediaFrame;

        if (!frame) {
            frame = window.wp.media({
                title: (cfg.i18n && cfg.i18n.mediaTitle) || '',
                button: { text: (cfg.i18n && cfg.i18n.mediaButton) || '' },
                multiple: true,
                library: { type: '' },
            });

            frame.on('select', function () {
                var editor = wrap.__zertiQuill;
                if (!editor) {
                    return;
                }
                frame.state().get('selection').each(function (attachment) {
                    insertAttachment(editor, attachment.toJSON());
                });
                syncEditor(wrap);
            });

            wrap.__zertiMediaFrame = frame;
        }

        frame.open();
    }

    function initEditor(wrap) {
        if (!wrap || wrap.getAttribute('data-zerti-rich-editor-bound') === '1') {
            return;
        }
        if (typeof window.Quill !== 'function') {
            return;
        }

        var textarea = wrap.querySelector('.zerti-rich-editor__source');
        if (!textarea) {
            return;
        }

        wrap.setAttribute('data-zerti-rich-editor-bound', '1');

        var mount = document.createElement('div');
        mount.className = 'zerti-rich-editor__quill';
        mount.setAttribute('dir', 'rtl');
        wrap.appendChild(mount);

        var minHeight = parseInt(wrap.getAttribute('data-zerti-rich-editor-min-height') || '160', 10);
        if (isNaN(minHeight) || minHeight < 80) {
            minHeight = 160;
        }

        var readonly = wrap.getAttribute('data-zerti-rich-editor-readonly') === '1' || textarea.disabled || textarea.readOnly;
        var placeholder =
            wrap.getAttribute('data-zerti-rich-editor-placeholder') ||
            textarea.getAttribute('placeholder') ||
            '';

        var quill = new window.Quill(mount, {
            theme: 'snow',
            readOnly: readonly,
            placeholder: placeholder,
            formats: EDITOR_FORMATS,
            modules: {
                toolbar: buildToolbarConfig(),
            },
        });

        quill.root.setAttribute('dir', 'rtl');
        quill.root.style.textAlign = 'right';
        quill.root.style.minHeight = minHeight + 'px';

        var initial = textarea.value || '';
        if (initial.trim() !== '') {
            quill.root.innerHTML = initial;
        }

        quill.on('text-change', function () {
            syncEditor(wrap);
        });

        wrap.__zertiQuill = quill;
        fixToolbarSvgViewBox(wrap);
        applyToolbarPickerLabels(wrap);
        bindMediaToolbarButton(wrap);
        syncEditor(wrap);
    }

    window.zertiSyncRichEditors = function (root) {
        var scope = root && root.querySelectorAll ? root : document;
        scope.querySelectorAll('[data-zerti-rich-editor]').forEach(syncEditor);
    };

    window.zertiInitRichEditors = function (root) {
        var scope = root && root.querySelectorAll ? root : document;
        scope.querySelectorAll('[data-zerti-rich-editor]').forEach(initEditor);
    };
})(window, document);
