(function($) {
    'use strict';

    // Глобальные переменные
    let $toolbar, $activeEditor = null, savedRange = null, currentLink = null, currentImage = null;
    // Хранит настройки плагина (чтобы иметь к ним доступ в других функциях)
    let pluginSettings = {};

    // --- ⬇️ НОВОЕ: вспомогательная функция для финализации выделения ⬇️ ---
    function finalizeSelection(range, wasCollapsed) {
        const sel = window.getSelection();
        sel.removeAllRanges();
        if (wasCollapsed) {
            const collapsed = range.cloneRange();
            collapsed.collapse(false);
            sel.addRange(collapsed);
            savedRange = collapsed.cloneRange();
        } else {
            sel.addRange(range);
            savedRange = range.cloneRange();
        }
    }
    // --------------------------------------------------------------------

    // Функция сохранения выделения
    function saveSelection() {
        const sel = window.getSelection();
        if (sel.rangeCount > 0) {
            savedRange = sel.getRangeAt(0).cloneRange();
        }
    }

    // Функция восстановления выделения
    function restoreSelection() {
        if (savedRange) {
            const sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(savedRange);
        }
    }

    // Очистка пустых тегов внутри редактора
    function cleanEmptyTags(editor) {
        // Удаляем пустые теги форматирования (кроме <i> - обрабатываем отдельно)
        editor.find('strong:empty, b:empty, em:empty, u:empty, s:empty, span:empty').remove();

        // Удаляем пустые <i> только если это НЕ Font Awesome иконка
        editor.find('i:empty').filter(function() {
            const classes = $(this).attr('class') || '';
            // Если есть FA классы - это иконка, не удаляем
            return !/\bfa[srbldk]?\b/.test(classes) && !/\bfa-/.test(classes);
        }).remove();
        editor.find('span').each(function() {
            if ($(this).html().trim() === '<br>' || $(this).html().trim() === '') {
                $(this).replaceWith($(this).html());
            }
        });
    }

    // Проверка, применён ли уже нужный формат
    function isActive(format) {
        if (!$activeEditor || !$activeEditor.length) return false;
        const sel = window.getSelection();
        if (!sel.rangeCount) return false;
        let node = sel.anchorNode;
        if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
        while (node && node !== $activeEditor[0]) {
            if (format === 'bold' && node.tagName && /^(b|strong)$/.test(node.tagName.toLowerCase())) return true;
            if (format === 'italic' && node.tagName && /^(i|em)$/.test(node.tagName.toLowerCase())) return true;
            if (format === 'underline' && node.tagName && node.tagName.toLowerCase() === 'u') return true;
            if (format === 'strike' && node.tagName && node.tagName.toLowerCase() === 's') return true;
            if (format === 'alignLeft' && node.style && node.style.textAlign === 'left') return true;
            if (format === 'alignCenter' && node.style && node.style.textAlign === 'center') return true;
            if (format === 'alignRight' && node.style && node.style.textAlign === 'right') return true;
            if (format === 'link' && node.tagName && node.tagName.toLowerCase() === 'a') return true;
            if (format === 'unorderedList' && node.tagName && node.tagName.toLowerCase() === 'ul') return true;
            if (format === 'orderedList' && node.tagName && node.tagName.toLowerCase() === 'ol') return true;
            node = node.parentNode;
        }
        return false;
    }

    // Переключение формата (жирный, курсив, подчёркивание, зачёркнутый)
    function toggleFormat(tagName) {
        restoreSelection();
        const sel = window.getSelection();
        if (!sel.rangeCount) return;
        let range = sel.getRangeAt(0);
        const wasCollapsed = range.collapsed;

        if (range.collapsed) {
            let node = sel.anchorNode;
            if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
            let remove = false, temp = node;
            while (temp && temp !== $activeEditor[0]) {
                if (temp.tagName && temp.tagName.toLowerCase() === tagName.toLowerCase()) {
                    remove = true;
                    break;
                }
                temp = temp.parentNode;
            }
            if (remove) {
                let marker = document.createElement('span');
                marker.appendChild(document.createTextNode("\u200B"));
                range.insertNode(marker);
                let parent = temp.parentNode;
                while(temp.firstChild) {
                    parent.insertBefore(temp.firstChild, temp);
                }
                parent.removeChild(temp);
                let newRange = document.createRange();
                newRange.selectNodeContents(marker);
                finalizeSelection(newRange, wasCollapsed);
                marker.parentNode.removeChild(marker);
                return;
            } else {
                let newNode = document.createElement(tagName);
                newNode.appendChild(document.createTextNode("\u200B"));
                range.insertNode(newNode);
                let newRange = document.createRange();
                newRange.selectNodeContents(newNode);
                finalizeSelection(newRange, wasCollapsed);
                return;
            }
        } else {
            let node = sel.anchorNode;
            if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
            let activeWrapper = null, temp = node;
            while (temp && temp !== $activeEditor[0]) {
                if (temp.tagName && temp.tagName.toLowerCase() === tagName.toLowerCase()){
                    activeWrapper = temp;
                    break;
                }
                temp = temp.parentNode;
            }
            if (activeWrapper) {
                let newRange = document.createRange();
                newRange.selectNodeContents(activeWrapper);
                let parent = activeWrapper.parentNode;
                while(activeWrapper.firstChild) {
                    parent.insertBefore(activeWrapper.firstChild, activeWrapper);
                }
                parent.removeChild(activeWrapper);
                finalizeSelection(newRange, wasCollapsed);
            } else {
                try {
                    let newNode = document.createElement(tagName);
                    range.surroundContents(newNode);
                    let newRange = document.createRange();
                    newRange.selectNodeContents(newNode);
                    finalizeSelection(newRange, wasCollapsed);
                } catch(e) {
                    let newNode = document.createElement(tagName);
                    newNode.appendChild(range.extractContents());
                    range.insertNode(newNode);
                    let newRange = document.createRange();
                    newRange.selectNodeContents(newNode);
                    finalizeSelection(newRange, wasCollapsed);
                }
            }
        }
    }

    // Применение размера шрифта
    function applyFontSize(size) {
        restoreSelection();
        const sel = window.getSelection();
        if (!sel.rangeCount) return;
        let range = sel.getRangeAt(0);
        const wasCollapsed = range.collapsed;
        const span = document.createElement('span');
        span.style.fontSize = size + 'px';
        if (range.collapsed) {
            span.appendChild(document.createTextNode("\u200B"));
            range.insertNode(span);
        } else {
            span.appendChild(range.extractContents());
            range.insertNode(span);
        }
        let newRange = document.createRange();
        newRange.selectNodeContents(span);
        finalizeSelection(newRange, wasCollapsed);
    }

    // Применение заголовка с сохранением выравнивания
    function applyHeader(headerTag) {
        restoreSelection();
        const sel = window.getSelection();
        if (!sel.rangeCount) return;
        const range = sel.getRangeAt(0);
        const wasCollapsed = range.collapsed;
        let block = $(range.commonAncestorContainer).closest('p,div,h1,h2,h3,h4,h5,h6')[0];
        if (block) {
            const newBlock = document.createElement(headerTag);
            newBlock.innerHTML = block.innerHTML;
            newBlock.style.textAlign = window.getComputedStyle(block).textAlign;
            block.parentNode.replaceChild(newBlock, block);
            let newRange = document.createRange();
            newRange.selectNodeContents(newBlock);
            finalizeSelection(newRange, wasCollapsed);
        }
    }

    // Применение ссылки с сохранением всех атрибутов и классов
    function applyLink(data) {
        restoreSelection();
        const sel = window.getSelection();
        if (!sel.rangeCount) return;
        const range = sel.getRangeAt(0);
        const wasCollapsed = range.collapsed;

        if (currentLink) {
            // Редактируем существующую ссылку - сохраняем все атрибуты и классы
            const $currentLink = $(currentLink);

            // Обновляем только нужные свойства
            $currentLink.attr('href', data.url);
            $currentLink.text(data.text || sel.toString() || data.url);

            // Управляем target
            if (data.newWindow) {
                $currentLink.attr('target', '_blank');
            } else {
                $currentLink.removeAttr('target');
            }

            // currentLink уже содержит все исходные классы и атрибуты
            currentLink = null;
        } else {
            // Создаем новую ссылку
            const a = document.createElement('a');
            a.href = data.url;
            a.textContent = data.text || sel.toString() || data.url;
            if (data.newWindow) a.target = '_blank';

            range.deleteContents();
            range.insertNode(a);

            // Добавляем droppable функциональность только для новых ссылок
            if (typeof $.fn.droppable === 'function') {
                $(a).droppable({
                    tolerance: 'pointer',
                    greedy: true,
                    over: function() { $(this).addClass('dropHere'); },
                    out: function() { $(this).removeClass('dropHere'); },
                    drop: function(event, ui) {
                        $(this).removeClass('dropHere');
                        $(this).attr('data-stype', ui.draggable.attr('data-ss'));
                        $('.skeletonAdded').addClass('saDone');
                        setTimeout(function() {
                            $('.skeletonAdded').removeClass('saDone');
                        }, 700);
                        event.stopPropagation();
                    }
                });
            }
        }

        let newRange = document.createRange();
        let targetElement = currentLink || document.querySelector(':focus'); // Находим обновленный элемент
        if (!targetElement && !currentLink) {
            // Если создавали новую ссылку, найдем ее через selection
            targetElement = sel.anchorNode.nodeType === Node.TEXT_NODE ?
                sel.anchorNode.parentNode : sel.anchorNode;
            if (targetElement.tagName !== 'A') {
                targetElement = targetElement.querySelector('a') || targetElement.closest('a');
            }
        }
        if (targetElement && targetElement.tagName === 'A') {
            newRange.selectNodeContents(targetElement);
            finalizeSelection(newRange, wasCollapsed);
        }
    }

    // Очистка форматирования
    function clearFormatting() {
        restoreSelection();
        const sel = window.getSelection();
        if (sel.rangeCount) {
            const initialCollapsed = sel.getRangeAt(0).collapsed;
            if (sel.isCollapsed) {
                let range = sel.getRangeAt(0);
                let marker = document.createElement("span");
                marker.appendChild(document.createTextNode("\u200B"));
                range.insertNode(marker);
                let newRange = document.createRange();
                newRange.selectNodeContents(marker);
                document.execCommand("removeFormat", false, null);
                finalizeSelection(newRange, initialCollapsed);
                marker.parentNode.removeChild(marker);
            } else {
                document.execCommand("removeFormat", false, null);
            }
        }
        if ($activeEditor) cleanEmptyTags($activeEditor);
    }

    // --- Выбор цвета текста и фона (jscolor или <input type="color">) с учётом выделения ---
    function chooseTextColor() {
        const applyColor = (newColor) => {
            restoreSelection();
            const sel = window.getSelection();
            if (!sel.rangeCount) return;
            let range = sel.getRangeAt(0);
            const wasCollapsed = range.collapsed;
            const span = document.createElement('span');
            span.style.color = newColor;
            if (range.collapsed) {
                span.appendChild(document.createTextNode("\u200B"));
                range.insertNode(span);
            } else {
                span.appendChild(range.extractContents());
                range.insertNode(span);
            }
            let newRange = document.createRange();
            newRange.selectNodeContents(span);
            finalizeSelection(newRange, wasCollapsed);
            updateToolbarState();
        };

        if (window.jscolor) {
            const $input = $('<input class="jscolor" style="display:none;">');
            $('body').append($input);
            const picker = new jscolor($input[0]);
            picker.show();
            $input.on('change', function() {
                const newColor = (this.jscolor && this.jscolor.toString().charAt(0) === '#' ? this.jscolor.toString() : '#' + this.value);
                applyColor(newColor);
                $input.remove();
            });
        } else {
            const $input = $('<input type="color" style="display:none;">');
            $('body').append($input);
            $input.trigger('click');
            $input.on('change', function() {
                applyColor(this.value);
                $input.remove();
            });
        }
    }

    function chooseBgColor() {
        const applyBg = (newColor) => {
            restoreSelection();
            const sel = window.getSelection();
            if (!sel.rangeCount) return;
            let range = sel.getRangeAt(0);
            const wasCollapsed = range.collapsed;
            const span = document.createElement('span');
            span.style.backgroundColor = newColor;
            if (range.collapsed) {
                span.appendChild(document.createTextNode("\u200B"));
                range.insertNode(span);
            } else {
                span.appendChild(range.extractContents());
                range.insertNode(span);
            }
            let newRange = document.createRange();
            newRange.selectNodeContents(span);
            finalizeSelection(newRange, wasCollapsed);
            updateToolbarState();
        };

        if (window.jscolor) {
            const $input = $('<input class="jscolor" style="display:none;">');
            $('body').append($input);
            const picker = new jscolor($input[0]);
            picker.show();
            $input.on('change', function() {
                const newColor = (this.jscolor && this.jscolor.toString().charAt(0) === '#' ? this.jscolor.toString() : '#' + this.value);
                applyBg(newColor);
                $input.remove();
            });
        } else {
            const $input = $('<input type="color" style="display:none;">');
            $('body').append($input);
            $input.trigger('click');
            $input.on('change', function() {
                applyBg(this.value);
                $input.remove();
            });
        }
    }

    // Выбор цвета фона с интеграцией jscolor
    function chooseBgColor() {
        if (window.jscolor) {
            const $input = $('<input class="jscolor" style="display:none;">');
            $('body').append($input);
            const picker = new jscolor($input[0]);
            picker.show();
            $input.on('change', function() {
                const newColor = (this.jscolor && this.jscolor.toString().charAt(0) === '#' ? this.jscolor.toString() : '#' + this.value);
                restoreSelection();
                const sel = window.getSelection();
                if (sel.rangeCount) {
                    let node = sel.anchorNode;
                    if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
                    const range = sel.getRangeAt(0);
                    const span = document.createElement('span');
                    span.style.backgroundColor = newColor;
                    if (range.collapsed) {
                        span.appendChild(document.createTextNode("\u200B"));
                        range.insertNode(span);
                        let newRange = document.createRange();
                        newRange.selectNodeContents(span);
                        newRange.collapse(false);
                        sel.removeAllRanges();
                        sel.addRange(newRange);
                        savedRange = newRange.cloneRange();
                    } else {
                        span.appendChild(range.extractContents());
                        range.insertNode(span);
                        let newRange = document.createRange();
                        newRange.selectNodeContents(span);
                        newRange.collapse(false);
                        sel.removeAllRanges();
                        sel.addRange(newRange);
                        savedRange = newRange.cloneRange();
                    }
                }
                updateToolbarState();
                $input.remove();
            });
        } else {
            const $input = $('<input type="color" style="display:none;">');
            $('body').append($input);
            $input.trigger('click');
            $input.on('change', function() {
                const newColor = this.value;
                restoreSelection();
                const sel = window.getSelection();
                if (sel.rangeCount) {
                    let node = sel.anchorNode;
                    if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
                    const range = sel.getRangeAt(0);
                    const span = document.createElement('span');
                    span.style.backgroundColor = newColor;
                    if (range.collapsed) {
                        span.appendChild(document.createTextNode("\u200B"));
                        range.insertNode(span);
                        let newRange = document.createRange();
                        newRange.selectNodeContents(span);
                        newRange.collapse(false);
                        sel.removeAllRanges();
                        sel.addRange(newRange);
                        savedRange = newRange.cloneRange();
                    } else {
                        span.appendChild(range.extractContents());
                        range.insertNode(span);
                        let newRange = document.createRange();
                        newRange.selectNodeContents(span);
                        newRange.collapse(false);
                        sel.removeAllRanges();
                        sel.addRange(newRange);
                        savedRange = newRange.cloneRange();
                    }
                }
                updateToolbarState();
                $input.remove();
            });
        }
    }

    // Открытие модального окна для ссылки
    function openLinkPopup(prefillData, callback) {
        let $popup = $('#editorLinkPopup');
        if ($popup.length === 0) {
            $popup = $(`
                <div id="editorLinkPopup">
                    <div class="celEMC">
                        <div>
                            <label>Ссылка: <input type="text" id="editorLinkUrl"></label>
                        </div>
                        <div>
                            <label>Анкор: <input type="text" id="editorLinkText"></label>
                        </div>
                        <div>
                            <input type="checkbox" id="editorLinkNewWindow">
                            <label for="editorLinkNewWindow">Открывать в новом окне</label>
                        </div>
                    </div>
                    <div class="celBs">
                        <button type="button" id="editorLinkOk" class="ceBtn ceSu">OK</button>
                        <button type="button" id="editorLinkCancel" class="ceBtn">Отмена</button>
                    </div>
                </div>
            `);
            $('body').append($popup);
            $(document).on('mousedown.linkPopup', function(e) {
                if (!$(e.target).closest('#editorLinkPopup').length &&
                    !$(e.target).closest('[data-action="link"]').length) {
                    $popup.hide();
                }
            });
        }
        const selectedText = window.getSelection().toString();
        $('#editorLinkUrl').val(prefillData && prefillData.url ? prefillData.url : '');
        $('#editorLinkText').val(prefillData && prefillData.text ? prefillData.text : (selectedText || ''));
        $('#editorLinkNewWindow').prop('checked', prefillData && prefillData.newWindow ? true : false);
        $popup.css({
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)'
        }).show();
        $('#editorLinkOk').off('click').on('click', function() {
            const url = $('#editorLinkUrl').val();
            const anchorText = $('#editorLinkText').val();
            const newWindow = $('#editorLinkNewWindow').is(':checked');
            $popup.hide();
            callback({url, text: anchorText, newWindow});
        });
        $('#editorLinkCancel').off('click').on('click', function() {
            $popup.hide();
        });
    }

    // Открытие модального окна для YouTube-видео
    function openVideoPopup(callback) {
        let $popup = $('#editorVideoPopup');
        if ($popup.length === 0) {
            $popup = $(`
                <div id="editorVideoPopup">
                    <div class="celEMC">
                        <label>YouTube URL:</label>
                        <input type="text" id="editorVideoUrl">
                    </div>
                    <div class="celBs">
                        <button type="button" id="editorVideoOk" class="ceBtn ceSu">OK</button>
                        <button type="button" id="editorVideoCancel" class="ceBtn">Отмена</button>
                    </div>
                </div>
            `);
            $('body').append($popup);
            $(document).on('mousedown.videoPopup', function(e) {
                if (!$(e.target).closest('#editorVideoPopup').length &&
                    !$(e.target).closest('[data-action="video"]').length) {
                    $popup.hide();
                }
            });
        }
        $('#editorVideoUrl').val('');
        $popup.css({
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)'
        }).show();
        $('#editorVideoOk').off('click').on('click', function() {
            const url = $('#editorVideoUrl').val();
            $popup.hide();
            callback(url);
        });
        $('#editorVideoCancel').off('click').on('click', function() {
            $popup.hide();
        });
    }

    // Открытие модального окна для редактирования изображения
    function openImagePopup(img) {
        currentImage = img;
        let $popup = $('#editorImagePopup');
        if ($popup.length === 0) {
            $popup = $(`
                <div id="editorImagePopup">
                    <div class="celEMC">
                        <div>
                            <label>Описание: <input type="text" id="imgAlt"></label>
                        </div>
                        <br>
                        <div class="celBs">
                            <label>Макс. ширина: <input type="number" id="imgMaxWidth"></label>
                            <label>Макс. высота: <input type="number" id="imgMaxHeight"></label>
                        </div>
                        <div>
                            <input type="checkbox" id="imgWrapLink">
                            <label for="imgWrapLink">Галерея</label>
                        </div>
                    </div>
                    <div class="celBs">
                        <button type="button" id="imgPopupOk" class="ceBtn ceSu">OK</button>
                        <button type="button" id="imgPopupCancel" class="ceBtn">Отмена</button>
                    </div>
                </div>
            `);
            $('body').append($popup);
            $(document).on('mousedown.imgPopup', function(e) {
                if (!$(e.target).closest('#editorImagePopup').length) {
                    $popup.hide();
                }
            });
        }
        $('#imgAlt').val($(img).attr('alt') || '');
        let computedMaxWidth = window.getComputedStyle(img).maxWidth;
        if (computedMaxWidth.indexOf('%') !== -1) {
            $('#imgMaxWidth').val('');
        } else {
            $('#imgMaxWidth').val(parseInt(computedMaxWidth) || '');
        }
        let computedMaxHeight = window.getComputedStyle(img).maxHeight;
        if (computedMaxHeight.indexOf('%') !== -1) {
            $('#imgMaxHeight').val('');
        } else {
            $('#imgMaxHeight').val(parseInt(computedMaxHeight) || '');
        }
        $('#imgWrapLink').prop('checked', false);
        $popup.show();
        $('#imgPopupOk').off('click').on('click', function() {
            const alt = $('#imgAlt').val();
            const maxWidth = $('#imgMaxWidth').val();
            const maxHeight = $('#imgMaxHeight').val();
            const wrapLink = $('#imgWrapLink').is(':checked');
            $(img).attr('alt', alt);
            if (maxWidth) $(img).css('max-width', maxWidth + 'px');
            if (maxHeight) $(img).css('max-height', maxHeight + 'px');
            if (wrapLink) {
                if ($(img).parent('a[data-fancybox="gallery"]').length === 0) {
                    $(img).wrap(`<a data-fancybox="gallery" href="${$(img).attr('src')}"></a>`);
                } else {
                    $(img).parent('a[data-fancybox="gallery"]').attr('href', $(img).attr('src'));
                }
            }
            $popup.hide();
        });
        $('#imgPopupCancel').off('click').on('click', function() {
            $popup.hide();
        });
    }

    // Обновление набора кнопок тулбара в соответствии с data-editor
    function updateToolbarButtons() {
        if (!$toolbar) return;
        if (!$activeEditor || !$activeEditor.attr('data-editor')) {
            $toolbar.find('.editor-btn, .editor-header, .editor-font-size').show();
            return;
        }
        const allowedArr = $activeEditor.attr('data-editor').split(',').map(s => s.trim());
        const shorthandMapping = {
            b: 'bold',
            i: 'italic',
            u: 'underline',
            ul: 'unorderedList',
            ol: 'orderedList',
            link: 'link',
            image: 'image',
            video: 'video',
            alignLeft: 'alignLeft',
            alignCenter: 'alignCenter',
            alignRight: 'alignRight',
            'text-color': 'textColor',
            'bg-color': 'backgroundColor',
            strike: 'strike'
        };
        const allowedActions = allowedArr.map(key => shorthandMapping[key] || key);
        $toolbar.find('.editor-btn').each(function() {
            const action = $(this).data('action');
            if (allowedActions.indexOf(action) === -1) {
                $(this).hide();
            } else {
                $(this).show();
            }
        });
        let headerAllowed = false;
        for (let i = 1; i <= 6; i++) {
            if (allowedActions.indexOf('h' + i) !== -1) {
                headerAllowed = true;
                break;
            }
        }
        $toolbar.find('.editor-header').toggle(headerAllowed);
        $toolbar.find('.editor-font-size').toggle(allowedActions.indexOf('font-size') !== -1);
    }

    // Обновление состояния тулбара
    function updateToolbarState() {
        // Определяем какой тулбар обновлять
        let $currentToolbar = $toolbar;
        if (pluginSettings.individualToolbar && $activeEditor) {
            const $indToolbar = $activeEditor.data('individualToolbar');
            if ($indToolbar && $indToolbar.length) {
                $currentToolbar = $indToolbar;
            }
        }
        if (!$currentToolbar || !$currentToolbar.length) return;

        $currentToolbar.find('.editor-btn').each(function() {
            const action = $(this).data('action');
            const formats = ['bold', 'italic', 'underline', 'strike', 'alignLeft', 'alignCenter', 'alignRight', 'link', 'unorderedList', 'orderedList'];
            if (formats.indexOf(action) !== -1) {
                isActive(action) ? $(this).addClass('active') : $(this).removeClass('active');
            }
        });
        const sel = window.getSelection();
        if (sel.rangeCount) {
            let node = sel.anchorNode;
            if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
            const tag = node.tagName ? node.tagName.toLowerCase() : '';
            $currentToolbar.find('.editor-header').val(tag.match(/^h[1-6]$/) ? tag : '');
            const computedSize = window.getComputedStyle(node).fontSize;
            const sizeVal = parseInt(computedSize, 10);
            const $fontSizeSelect = $currentToolbar.find('.editor-font-size');
            $fontSizeSelect.val($fontSizeSelect.find(`option[value="${sizeVal}"]`).length > 0 ? sizeVal : '');
        }
        updateToolbarButtons();
    }

    // Позиционирование тулбара так, чтобы он всегда был виден
    function positionToolbar() {
        if (!$toolbar || !$activeEditor || !$activeEditor.length) return;

        // Если включен режим статичного размещения (fixed: true) – или если редактор создан из textarea (alwaysShowToolbar)
        // тогда тулбар перемещается непосредственно перед редактором
        if (pluginSettings.fixed || $activeEditor.data('alwaysShowToolbar')) {
            $toolbar.detach();
            $activeEditor.before($toolbar);
            $toolbar.css({
                position: 'static',
                display: 'inline-flex'
            }).addClass('celenaETOpen');
            return;
        }

        const editorRect = $activeEditor[0].getBoundingClientRect();
        const toolbarHeight = $toolbar.outerHeight();
        const toolbarWidth = $toolbar.outerWidth();
        const windowWidth = $(window).width();
        const windowHeight = $(window).height();

        const spaceAbove = editorRect.top;
        const spaceBelow = windowHeight - editorRect.bottom;

        let top;
        if (spaceAbove >= toolbarHeight + 5) {
            top = editorRect.top - toolbarHeight - 5;
        } else if (spaceBelow >= toolbarHeight + 5) {
            top = editorRect.bottom + 5;
        } else {
            top = 5;
        }

        let left = editorRect.left;
        if (left + toolbarWidth > windowWidth) {
            left = windowWidth - toolbarWidth - 5;
        }

        $toolbar.css({
            position: 'fixed',
            top: top,
            left: left,
            display: 'inline-flex'
        }).addClass('celenaETOpen');
    }

    // Основной обработчик действий тулбара
    function handleAction(action) {
        restoreSelection();
        switch (action) {
            case 'bold':
                toggleFormat('strong');
                break;
            case 'italic':
                toggleFormat('em');
                break;
            case 'underline':
                toggleFormat('u');
                break;
            case 'strike':
                toggleFormat('s');
                break;
            case 'unorderedList':
                document.execCommand('insertUnorderedList');
                break;
            case 'orderedList':
                document.execCommand('insertOrderedList');
                break;
            case 'alignLeft':
                document.execCommand('justifyLeft');
                break;
            case 'alignCenter':
                document.execCommand('justifyCenter');
                break;
            case 'alignRight':
                document.execCommand('justifyRight');
                break;
            case 'link':
                let prefillData = {};
                const sel = window.getSelection();
                if (sel.rangeCount) {
                    let node = sel.anchorNode;
                    if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
                    const linkNode = $(node).closest('a')[0];
                    if (linkNode) {
                        prefillData = {
                            url: $(linkNode).attr('href'),
                            text: $(linkNode).text(),
                            newWindow: $(linkNode).attr('target') === '_blank'
                        };
                        currentLink = linkNode;
                    }
                }
                openLinkPopup(prefillData, function(data) {
                    applyLink(data);
                    updateToolbarState();
                });
                break;
            case 'icon':
                saveSelection();
                if (typeof IconEditor !== 'undefined' && IconEditor.insert) {
                    IconEditor.insert(null); // null = вставить в позицию курсора
                } else {
                    console.warn('[celenaEditor] IconEditor module not loaded');
                }
                break;
            case 'image': {
                // Проверяем, установлен ли курсор в редакторе
                const sel = window.getSelection();
                if (!sel.rangeCount || !$activeEditor || !$activeEditor.length) {
                    $.server_say({
                        say: "Вставьте курсор в то место, куда должно быть добавлено изображение",
                        status: "error"
                    });
                    return;
                }

                const $input = $('<input type="file" accept="image/*" multiple style="display:none;">');
                $('body').append($input);
                $input.trigger('click');
                $input.on('change', function(e) {
                    // Останавливаем всплытие события
                    e.stopPropagation();
                    e.preventDefault();

                    const files = Array.from(this.files);
                    if (!files.length) return;

                    restoreSelection();

                    // Добавляем анимацию спиннера, если она еще не добавлена
                    if (!document.getElementById('spinner-animation')) {
                        const style = document.createElement('style');
                        style.id = 'spinner-animation';
                        style.textContent = `
                            @keyframes spin {
                                0% { transform: rotate(0deg); }
                                100% { transform: rotate(360deg); }
                            }
                        `;
                        document.head.appendChild(style);
                    }

                    // Создаем общий прелоадер для всех изображений
                    const placeholder = document.createElement('div');
                    placeholder.className = 'images_load';
                    placeholder.style.cssText = `
                        display: inline-block;
                        padding: 10px;
                        border: 1px dashed #ccc;
                        border-radius: 5px;
                        margin: 5px;
                        background-color: #f9f9f9;
                        text-align: center;
                    `;

                    // Создаем содержимое прелоадера
                    const spinner = document.createElement('div');
                    spinner.style.cssText = `
                        display: inline-block;
                        width: 20px;
                        height: 20px;
                        border: 2px solid #f3f3f3;
                        border-top: 2px solid #3498db;
                        border-radius: 50%;
                        animation: spin 1s linear infinite;
                        margin-right: 10px;
                        vertical-align: middle;
                    `;

                    const text = document.createElement('span');
                    text.textContent = `Загружается ${files.length} ${files.length === 1 ? 'изображение' : files.length < 5 ? 'изображения' : 'изображений'}...`;
                    text.style.cssText = `
                        font-size: 12px;
                        color: #666;
                        vertical-align: middle;
                    `;

                    placeholder.appendChild(spinner);
                    placeholder.appendChild(text);

                    const range = sel.getRangeAt(0);
                    range.insertNode(placeholder);

                    // Формируем FormData со всеми файлами
                    const formData = new FormData();
                    files.forEach((file, index) => {
                        formData.append(`files[]`, file); // используем массив файлов
                    });
                    formData.append('ajax', 'UploadImages');
                    formData.append('csrf_token', encodeURIComponent(CSRF_TOKEN));

                    $.ajax({
                        url: window.location.href,
                        method: 'POST',
                        data: formData,
                        processData: false,
                        contentType: false,
                        success: function(response) {
                            console.log(response);
                            // Заменяем прелоадер на полученный контент
                            $(placeholder).replaceWith(response);

                            // Добавьте эти строки для синхронизации:
                            const sourceTextarea = $activeEditor.data('sourceTextarea');
                            if (sourceTextarea) {
                                sourceTextarea.val($activeEditor.html());
                            }
                        },
                        error: function(xhr, status, error) {
                            // В случае ошибки удаляем прелоадер и показываем сообщение
                            $(placeholder).remove();
                            $.server_say({
                                say: `Ошибка загрузки изображений: ${error}`,
                                status: "error"
                            });
                        },
                        complete: function() {
                            updateToolbarState();
                            positionToolbar();
                        }
                    });

                    $input.remove();
                });
                break;
            }
            case 'video':
                openVideoPopup(function(url) {
                    restoreSelection();
                    const regExp = /^.*(?:youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/;
                    const match = url.match(regExp);
                    if (match && match[1].length === 11) {
                        const videoId = match[1];
                        const embedHtml = `<iframe width="560" height="315" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allowfullscreen></iframe>`;
                        document.execCommand('insertHTML', false, embedHtml);
                    }
                    updateToolbarState();
                    positionToolbar();
                });
                break;
            case 'textColor':
                chooseTextColor();
                break;
            case 'backgroundColor':
                chooseBgColor();
                break;
            case 'removeFormat':
                clearFormatting();
                break;
        }
        updateToolbarState();
    }

    // Построение тулбара
    function buildToolbar(settings) {
        $toolbar.empty();
        settings.toolbarButtons.forEach(button => {
            if (button.action && button.action.match(/^h[1-6]$/)) return;
            const $btn = $(`<button type="button" class="editor-btn" data-action="${button.action}">${button.icon}</button>`);
            $toolbar.append($btn);
        });
        $toolbar.append(`<button type="button" class="editor-btn" data-action="removeFormat"><svg x="0" y="0" viewBox="0 0 32 32" style="enable-background:new 0 0 15 15"><g><path d="M30.75 14.75a4.27 4.27 0 0 0 0-6l-7.47-7.5a4.37 4.37 0 0 0-6 0l-16 16a4.27 4.27 0 0 0 0 6l7.47 7.47a4.27 4.27 0 0 0 6 0zm-12-12a2.13 2.13 0 0 1 3 0l7.47 7.47a2.13 2.13 0 0 1 0 3l-11 11L7.74 13.77zm-5.51 26.49a2.21 2.21 0 0 1-3 0l-7.48-7.47a2.13 2.13 0 0 1 0-3l3.47-3.47 10.49 10.47zM30.93 29.87H19.2a1.07 1.07 0 1 0 0 2.13h11.73a1.07 1.07 0 1 0 0-2.13z"></path></g></svg></button>`);
        const headerSelect = `
            <select class="editor-header">
                <option value="">p</option>
                <option value="h1">H1</option>
                <option value="h2">H2</option>
                <option value="h3">H3</option>
                <option value="h4">H4</option>
                <option value="h5">H5</option>
                <option value="h6">H6</option>
            </select>`;
        $toolbar.append(headerSelect);
        const fontSizeSelect = `
            <select class="editor-font-size">
                <option value="">Font Size</option>
                <option value="10">10px</option>
                <option value="12">12px</option>
                <option value="14">14px</option>
                <option value="16">16px</option>
                <option value="18">18px</option>
                <option value="24">24px</option>
                <option value="36">36px</option>
                <option value="48">48px</option>
                <option value="72">72px</option>
            </select>`;
        $toolbar.append(fontSizeSelect);
        settings.customModules.forEach(module => {
            if (module.button) {
                const $btn = $(module.button);
                $btn.attr('data-module', module.name);
                $toolbar.append($btn);
            }
        });
        $toolbar.find('.editor-header').on('change', function() {
            const header = $(this).val();
            restoreSelection();
            if (header) {
                applyHeader(header);
            } else {
                document.execCommand('formatBlock', false, 'p');
            }
            updateToolbarState();
        });
        $toolbar.find('.editor-font-size').on('change', function() {
            const size = $(this).val();
            restoreSelection();
            if (size) {
                applyFontSize(size);
            }
            updateToolbarState();
        });
    }

    // Инициализация тулбара (создаётся один раз)
    function initToolbar(settings) {
        if ($('#celenaEditorToolbar').length === 0) {
            $('body').append('<div id="celenaEditorToolbar"></div>');
        }
        $toolbar = $('#celenaEditorToolbar');
        buildToolbar(settings);
    }

    // Глобальные события для редактора и тулбара
    if (!$.celenaEditorGlobalEvents) {
        $.celenaEditorGlobalEvents = true;
        $(document).on('mousedown', function(e) {
            if (!$(e.target).closest('.celenaEditor, #celenaEditorToolbar, #editorLinkPopup, #editorVideoPopup, #editorImagePopup').length) {
                // Если активный редактор должен всегда показывать тулбар (например, при использовании textarea), не скрываем его
                if ($activeEditor && $activeEditor.data('alwaysShowToolbar')) {
                    return;
                }
                $toolbar && $toolbar.hide();
                if ($activeEditor) {
                    cleanEmptyTags($activeEditor);
                    $activeEditor = null;
                }
            }
        });
        $(document).on('click', '.celenaEditor a', function(e) {
            e.preventDefault();
            currentLink = $(this);
            openLinkPopup({
                url: currentLink.attr('href'),
                text: currentLink.text(),
                newWindow: currentLink.attr('target') === '_blank'
            }, function(data) {
                applyLink(data);
                updateToolbarState();
            });
        });
        $(document).on('click', '.celenaEditor img', function(e) {
            e.stopPropagation();
            e.preventDefault();
            openImagePopup(this);
        });
        $(window).on('scroll resize', function() {
            positionToolbar();
        });
    }

    // Ключевой обработчик клика в редакторе: устанавливаем каретку в место клика,
    // но если уже есть выделение – не сбрасываем его (решает проблему выделения текста)
    if (!$.celenaEditorEditorEvents) {
        $.celenaEditorEditorEvents = true;
        $(document).on('mousedown', '.celenaEditor, .celenaEditor *', function(e) {
            if ($(e.target).is('img')) return;

            // Находим родительский .celenaEditor
            const $editor = $(e.target).closest('.celenaEditor');
            if (!$editor.length) return;

            if (!$editor.attr('contenteditable')) {
                $editor.attr('contenteditable', true);
            }

            // Устанавливаем активный редактор
            $activeEditor = $editor;

            // Позволяем браузеру обработать клик естественным образом
            setTimeout(function() {
                const sel = window.getSelection();
                if (sel.rangeCount > 0) {
                    savedRange = sel.getRangeAt(0).cloneRange();
                }
                positionToolbar();
                updateToolbarState();
            }, 0);
        });

        // При изменениях синхронизируем содержимое (и чистим маркеры форматирования)
        $(document).on('keyup input mouseup', '.celenaEditor', function() {
            saveSelection();
            positionToolbar();
            updateToolbarState();
            // Если внутри тега форматирования (например <strong>) остался только символ ZERO WIDTH SPACE, очищаем его
            $(this).find('strong, em, u, s').each(function() {
                if ($(this).text() === "\u200B") {
                    $(this).empty();
                }
            });
            const sourceTextarea = $(this).data('sourceTextarea');
            if (sourceTextarea) {
                sourceTextarea.val($(this).html());
            }
        });

        $(document).on('click', '#celenaEditorToolbar .editor-btn, .celenaEditorToolbar .editor-btn', function(e) {
            // Останавливаем всплытие события
            e.stopPropagation();
            e.preventDefault();

            const action = $(this).data('action');
            if (action) {
                handleAction(action);
            }
        });
    }

    // Дополнительное событие для CTRL+A
    $(document).on('keydown', '.celenaEditor', function(e) {
        if (e.ctrlKey && e.keyCode === 65) {
            setTimeout(function() {
                saveSelection();
                updateToolbarState();
            }, 0);
        }
    });

    // Основной плагин: предотвращаем повторную инициализацию
    $.fn.celenaEditor = function(options) {
        this.each(function() {
            if ($(this).data('celenaEditorInitialized')) {
                return;
            }
            $(this).data('celenaEditorInitialized', true);

            // Если элемент является textarea, создаём новый редактор, скрываем textarea
            // и отмечаем, что тулбар для этого редактора должен быть всегда виден
            if ($(this).is('textarea')) {
                const $textarea = $(this);
                const initialContent = $textarea.val();
                const $editor = $('<div class="celenaEditor" contenteditable="true"></div>');
                $editor.html(initialContent);
                $textarea.after($editor).hide();
                // Сохраняем ссылку на исходный textarea для последующей синхронизации содержимого
                $editor.data('sourceTextarea', $textarea);
                // Флаг для автоматического отображения тулбара над элементом, созданным из textarea
                $editor.data('alwaysShowToolbar', true);
            } else {
                $(this).addClass('celenaEditor');
            }
        });

        const settings = $.extend({
            toolbarButtons: [
                { action: 'bold', icon: '<svg x="0" y="0" viewBox="0 0 181.395 181.395" style="enable-background:new 0 0 15 15"><g><path d="M20.618 181.395V0h62.293c22.506 0 40.074 4.174 52.699 12.521 12.623 8.346 18.936 20.785 18.936 37.313 0 8.639-2.033 16.318-6.104 23.049-4.07 6.729-10.34 11.795-18.813 15.199 10.631 2.408 18.479 7.246 23.547 14.514 5.064 7.268 7.6 15.637 7.6 25.104 0 17.691-5.939 31.064-17.814 40.115-11.879 9.055-28.904 13.58-51.082 13.58H20.618zM62.853 75.623h20.93c9.551-.166 16.695-2.014 21.43-5.545 4.734-3.529 7.102-8.699 7.102-15.51 0-7.725-2.41-13.35-7.225-16.881-4.82-3.529-12.211-5.295-22.178-5.295H62.853v43.231zm0 27.908v45.473H91.88c8.971 0 15.699-1.766 20.184-5.297 4.484-3.529 6.729-8.947 6.729-16.256 0-7.891-1.932-13.85-5.795-17.879-3.861-4.027-10.111-6.041-18.748-6.041H62.853z"></path></g></svg>' },
                { action: 'italic', icon: '<svg x="0" y="0" viewBox="0 0 512 512" style="enable-background:new 0 0 15 15"><g><path d="M434.571 23.857v35.714c0 9.862-7.995 17.857-17.857 17.857H346.67l-89.286 357.143h52.188c9.862 0 17.857 7.995 17.857 17.857v35.714c0 9.862-7.995 17.857-17.857 17.857H95.286c-9.862 0-17.857-7.995-17.857-17.857v-35.714c0-9.862 7.995-17.857 17.857-17.857h70.045l89.286-357.143H202.43c-9.862 0-17.857-7.995-17.857-17.857V23.857C184.573 13.995 192.568 6 202.43 6h214.286c9.861 0 17.855 7.995 17.855 17.857z"></path></g></svg>' },
                { action: 'underline', icon: '<svg x="0" y="0" viewBox="0 0 300 300" style="enable-background:new 0 0 15 15"><g><path d="M230 0c-8.284 0-15 6.716-15 15v130c0 35.841-29.16 65-65.002 65-17.362 0-33.684-6.762-45.961-19.038C91.759 178.685 84.999 162.361 85 144.999V15c0-8.284-6.716-15-15-15S55 6.716 55 15v129.998c-.001 25.375 9.879 49.232 27.823 67.177 17.943 17.943 41.8 27.825 67.175 27.825C202.382 240 245 197.383 245 145V15c0-8.284-6.716-15-15-15zM230 270H70c-8.284 0-15 6.716-15 15s6.716 15 15 15h160c8.284 0 15-6.716 15-15s-6.716-15-15-15z"></path></g></svg>' },
                { action: 'strike', icon: '<svg x="0" y="0" viewBox="0 0 60 60" style="enable-background:new 0 0 15 15"><g><path d="M58 30a3 3 0 0 0-3-3H5a3 3 0 0 0 0 6h50a3 3 0 0 0 3-3zM30 8a9.917 9.917 0 0 1 9.808 7.612 3 3 0 1 0 5.864-1.223A15.913 15.913 0 0 0 30 2a15.774 15.774 0 0 0-16 15.5 15.009 15.009 0 0 0 2.017 7.5h7.868A9.322 9.322 0 0 1 20 17.5 9.771 9.771 0 0 1 30 8zM30 52a9.917 9.917 0 0 1-9.808-7.612 3 3 0 1 0-5.864 1.223A15.913 15.913 0 0 0 30 58a15.774 15.774 0 0 0 16-15.5 15.009 15.009 0 0 0-2.017-7.5h-7.868A9.322 9.322 0 0 1 40 42.5 9.771 9.771 0 0 1 30 52z"></path></g></svg>' },
                { action: 'unorderedList', icon: '<svg x="0" y="0" viewBox="0 0 60.123 60.123" style="enable-background:new 0 0 15 15"><g><path d="M57.124 51.893H16.92a3 3 0 1 1 0-6h40.203a3 3 0 0 1 .001 6zM57.124 33.062H16.92a3 3 0 1 1 0-6h40.203a3 3 0 0 1 .001 6zM57.124 14.231H16.92a3 3 0 1 1 0-6h40.203a3 3 0 0 1 .001 6z"><circle cx="4.029" cy="11.463" r="4.029"></circle><circle cx="4.029" cy="30.062" r="4.029"></circle><circle cx="4.029" cy="48.661" r="4.029"></circle></g></svg>' },
                { action: 'orderedList', icon: '<svg x="0" y="0" viewBox="0 0 317.109 317.109" style="enable-background:new 0 0 15 15"><g><path d="M102.109 53.555h200c8.284 0 15-6.716 15-15s-6.716-15-15-15h-200c-8.284 0-15 6.716-15 15s6.716 15 15 15zM302.109 143.555h-200c-8.284 0-15 6.716-15 15 0 8.284 6.716 15 15 15h200c8.284 0 15-6.716 15-15 0-8.285-6.715-15-15-15zM302.109 263.555h-200c-8.284 0-15 6.716-15 15 0 8.284 6.716 15 15 15h200c8.284 0 15-6.716 15-15 0-8.285-6.715-15-15-15zM17.826 49.036V86.6c0 4.074 3.32 7.146 7.724 7.146 4.33 0 7.721-3.139 7.721-7.146V30.426c0-3.96-3.247-7.063-7.392-7.063-3.646 0-5.47 2.446-6.069 3.25l-.075.104-6.526 9.232c-1.267 1.378-2.394 3.582-2.394 5.696-.001 4.03 3.133 7.317 7.011 7.391zM7.63 193.746h29.406c3.849 0 6.981-3.391 6.981-7.559 0-4.124-3.131-7.479-6.981-7.479H15.684v-.123c0-2.245 5.148-5.878 9.285-8.797 8.229-5.807 18.47-13.033 18.47-25.565 0-11.893-9.216-20.86-21.438-20.86-11.703 0-20.527 8.044-20.527 18.711 0 6.19 4.029 8.387 7.479 8.387 4.938 0 7.889-3.677 7.889-7.23 0-2.209.568-4.745 4.994-4.745 5.979 0 6.151 5.298 6.151 5.902 0 4.762-6.18 9.214-12.157 13.519C8.442 163.228.068 169.26.068 178.587v8.012c-.001 4.275 3.91 7.147 7.562 7.147zM42.446 242.783c0-12.342-7.288-19.42-19.994-19.42-16.66 0-21.062 11.898-21.062 18.189 0 7.324 5.445 8.115 7.786 8.115 4.559 0 7.621-3.063 7.621-7.622 0-1.754.624-3.767 5.487-3.767 3.495 0 4.918.504 4.918 5.568 0 4.948-1.062 5.487-5.245 5.487-4.018 0-7.047 3.171-7.047 7.375 0 4.159 3.066 7.296 7.131 7.296 5.525 0 6.635 2.256 6.635 5.897v1.559c0 6.126-2.389 7.287-6.798 7.287-6.083 0-6.556-3.132-6.556-4.092 0-3.631-2.407-7.295-7.785-7.295-4.72 0-7.538 2.941-7.538 7.869 0 8.976 7.696 18.516 21.958 18.516 13.854 0 22.126-8.331 22.126-22.285v-1.559c0-5.721-1.83-10.465-5.264-13.876 2.352-3.403 3.627-7.944 3.627-13.242z"></path></g></svg>' },
                { action: 'alignLeft', icon: '<svg x="0" y="0" viewBox="0 0 24 24" style="enable-background:new 0 0 15 15"><g><path d="M3 4h18a1 1 0 0 0 0-2H3a1 1 0 0 0 0 2zM3 10h12a1 1 0 0 0 0-2H3a1 1 0 0 0 0 2zM3 16h18a1 1 0 0 0 0-2H3a1 1 0 0 0 0 2zM3 22h12a1 1 0 0 0 0-2H3a1 1 0 0 0 0 2z"></path></g></svg>' },
                { action: 'alignCenter', icon: '<svg x="0" y="0" viewBox="0 0 72 72" style="enable-background:new 0 0 15 15"><g><path d="M63 15H9c-1.3 0-3 1.3-3 3s1.3 3 3 3h54c1.3 0 3-1.3 3-3s-1.3-3-3-3zM54 31H18c-1.3 0-3 1.3-3 3s1.3 3 3 3h36c1.3 0 3-1.3 3-3s-1.3-3-3-3zM63 47H9c-1.3 0-3 1.3-3 3s1.3 3 3 3h54c1.3 0 3-1.3 3-3s-1.3-3-3-3zM54 63H18c-1.3 0-3 1.3-3 3s1.3 3 3 3h36c1.3 0 3-1.3 3-3s-1.3-3-3-3z"></path></g></svg>' },
                { action: 'alignRight', icon: '<svg x="0" y="0" viewBox="0 0 24 24" style="enable-background:new 0 0 15 15"><g><path d="M21 2H3a1 1 0 0 0 0 2h18a1 1 0 0 0 0-2zM21 10a1 1 0 0 0 0-2H9a1 1 0 0 0 0 2zM2 15a1 1 0 0 0 1 1h18a1 1 0 0 0 0-2H3a1 1 0 0 0-1 1zM22 21a1 1 0 0 0-1-1H9a1 1 0 0 0 0 2h12a1 1 0 0 0 1-1z"></path></g></svg>' },
                { action: 'link', icon: '<svg x="0" y="0" viewBox="0 0 512 512" style="enable-background:new 0 0 15 15"><g><path d="M307.148 35.148 203.081 139.214c-.201.2-.326.443-.526.645 25.637-3.734 51.974-1.174 76.388 8.346l70.63-70.63c23.399-23.399 61.454-23.399 84.853 0 23.399 23.397 23.399 61.454 0 84.851-3.99 3.992-110.083 110.085-104.066 104.066-23.584 23.586-62.276 22.577-84.853 0-11.693-11.693-30.731-11.693-42.426 0l-18.214 18.214c5.052 8.584 10.844 16.844 18.214 24.214 44.44 44.44 120.934 47.99 169.061.526.201-.2.443-.326.645-.526l104.066-104.066c46.862-46.864 46.862-122.842 0-169.706-46.864-46.864-122.841-46.864-169.705 0z"></path><path d="m233.285 363.568-70.858 70.858c-23.397 23.399-61.454 23.399-84.851 0-23.399-23.399-23.399-61.454 0-84.853L181.869 245.28c23.584-23.584 62.276-22.577 84.853 0 11.693 11.695 30.732 11.695 42.426 0l18.214-18.214c-5.052-8.584-10.844-16.844-18.214-24.212-44.355-44.357-120.793-48.131-169.061-.527-.201.2-.443.326-.645.527L35.148 307.148c-46.862 46.862-46.864 122.842 0 169.706 46.864 46.862 122.844 46.862 169.706 0l104.293-104.295c.201-.2.326-.441.526-.645-25.637 3.734-51.973 1.174-76.388-8.346z"></path></g></svg>' },
                { action: 'image', icon: '<svg x="0" y="0" viewBox="0 0 100 100" style="enable-background:new 0 0 15 15"><g><path d="M11.5 86.5h77c2.75 0 5-2.25 5-5v-63c0-2.75-2.25-5-5-5h-77c-2.75 0-5 2.25-5 5v63c0 2.75 2.25 5 5 5zm63.54-63.11c4.77 0 8.64 3.87 8.64 8.64s-3.87 8.64-8.64 8.64-8.64-3.87-8.64-8.64 3.87-8.64 8.64-8.64zM15.79 72.45l22.19-30.7c1.61-2.23 4.25-2.23 5.86 0l13.12 18.14c1.61 2.23 4.25 2.23 5.86 0l3.57-4.94c1.61-2.23 4.25-2.23 5.86 0l12.65 17.5c1.61 2.23.68 4.05-2.07 4.05H17.86c-2.75 0-3.68-1.82-2.07-4.05z"></path></g></svg>' },
                { action: 'icon', icon: '<svg viewBox="0 0 512 512" style="enable-background:new 0 0 15 15"><path d="M256 48C141.1 48 48 141.1 48 256s93.1 208 208 208 208-93.1 208-208S370.9 48 256 48zm0 336c-70.7 0-128-57.3-128-128s57.3-128 128-128 128 57.3 128 128-57.3 128-128 128z"/></svg>' },
                { action: 'video', icon: '<svg x="0" y="0" viewBox="0 0 310 310" style="enable-background:new 0 0 15 15"><g><path d="M297.917 64.645c-11.19-13.302-31.85-18.728-71.306-18.728H83.386c-40.359 0-61.369 5.776-72.517 19.938C0 79.663 0 100.008 0 128.166v53.669c0 54.551 12.896 82.248 83.386 82.248h143.226c34.216 0 53.176-4.788 65.442-16.527C304.633 235.518 310 215.863 310 181.835v-53.669c0-29.695-.841-50.16-12.083-63.521zm-98.896 97.765-65.038 33.991a9.997 9.997 0 0 1-14.632-8.863v-67.764a10 10 0 0 1 14.609-8.874l65.038 33.772a10 10 0 0 1 .023 17.738z"></path></g></svg>' },
                { action: 'textColor', icon: '<svg x="0" y="0" viewBox="0 0 4335 4335" style="enable-background:new 0 0 15 15" fill-rule="evenodd"><g><path d="m4117 2936 2 5 2 5 4 9v1l2 5v1l4 9 2 5 2 5 4 9v1l2 5v1l2 5 2 5 2 5 2 5 2 5 1 2 2 6 4 13 1 3 1 3 3 11 1 5 1 4 3 12 1 3 1 2 4 15v2l1 5 3 13v3l3 15 1 5 3 16v2l2 16 1 5c1 6 1 12 2 17v1l1 17v2c0 7 1 13 1 20l1 19v21c0 455-369 824-824 824s-824-369-824-824v-21c0-6 0-13 1-19 0-7 1-13 1-20v-2c0-6 1-11 1-17v-1c1-6 1-12 2-17l1-5 2-16v-2l3-16 1-5 3-15v-3l3-13 1-5v-2l4-15 1-2 1-3 3-12 1-4 1-5 3-11 1-3 1-3 4-13 2-6 1-2 2-5 2-5 2-5 2-5 2-5v-1l4-9 2-5 2-5 4-9v-1l2-5v-1l4-9 2-5 2-5 2-5 693-1504v-18h110v18l693 1504zM199 3835 1403 277h729l647 1919-396 859-2 5-2 5-2 5-4 9v1l-2 5v1l-4 9-2 5-2 5-4 9v1l-2 5v1l-16-52H1190l-239 766H200zm1165-1326h802l-393-1254h-14z"></path></g></svg>' }
            ],
            customModules: [],
            includeBgColor: false,
            fixed: false, // По умолчанию тулбар позиционируется с position: fixed. Если установить true, то будет статичным.
            individualToolbar: false // false = один тулбар на все редакторы (перепрыгивает), true = каждому редактору свой тулбар
        }, options);

        // Сохраняем настройки для использования в других функциях
        pluginSettings = settings;

        if (settings.individualToolbar) {
            // Режим: каждому редактору свой тулбар
            this.each(function() {
                let $editor;
                if ($(this).is('textarea')) {
                    $editor = $(this).next('.celenaEditor');
                } else {
                    $editor = $(this);
                }

                if ($editor.length > 0) {
                    // Создаем уникальный тулбар для этого редактора
                    const toolbarId = 'celenaEditorToolbar_' + Math.random().toString(36).substr(2, 9);
                    const $individualToolbar = $('<div id="' + toolbarId + '" class="celenaEditorToolbar"></div>');
                    $editor.before($individualToolbar);

                    // Строим кнопки тулбара
                    buildToolbarForElement($individualToolbar, settings);

                    // Сохраняем ссылку на тулбар в data редактора
                    $editor.data('individualToolbar', $individualToolbar);

                    // Показываем тулбар сразу (статичный режим)
                    $individualToolbar.css({
                        position: 'static',
                        display: 'inline-flex'
                    }).addClass('celenaETOpen');
                }
            });
        } else {
            // Режим по умолчанию: один тулбар на все редакторы
            initToolbar(settings);

            // Если плагин применяется к textarea, сразу находим соответствующий редактор,
            // назначаем его активным и отображаем тулбар над ним
            this.filter('textarea').each(function() {
                const $editor = $(this).next('.celenaEditor');
                if ($editor.length > 0) {
                    $activeEditor = $editor;
                    positionToolbar();
                    updateToolbarState();
                    $toolbar.show();
                }
            });
        }

        return this;
    };

    // Построение тулбара для конкретного элемента (режим individualToolbar)
    function buildToolbarForElement($targetToolbar, settings) {
        $targetToolbar.empty();
        settings.toolbarButtons.forEach(button => {
            if (button.action && button.action.match(/^h[1-6]$/)) return;
            const $btn = $(`<button type="button" class="editor-btn" data-action="${button.action}">${button.icon}</button>`);
            $targetToolbar.append($btn);
        });
        $targetToolbar.append(`<button type="button" class="editor-btn" data-action="removeFormat"><svg x="0" y="0" viewBox="0 0 32 32" style="enable-background:new 0 0 15 15"><g><path d="M30.75 14.75a4.27 4.27 0 0 0 0-6l-7.47-7.5a4.37 4.37 0 0 0-6 0l-16 16a4.27 4.27 0 0 0 0 6l7.47 7.47a4.27 4.27 0 0 0 6 0zm-12-12a2.13 2.13 0 0 1 3 0l7.47 7.47a2.13 2.13 0 0 1 0 3l-11 11L7.74 13.77zm-5.51 26.49a2.21 2.21 0 0 1-3 0l-7.48-7.47a2.13 2.13 0 0 1 0-3l3.47-3.47 10.49 10.47zM30.93 29.87H19.2a1.07 1.07 0 1 0 0 2.13h11.73a1.07 1.07 0 1 0 0-2.13z"></path></g></svg></button>`);
        const headerSelect = `
            <select class="editor-header">
                <option value="">p</option>
                <option value="h1">H1</option>
                <option value="h2">H2</option>
                <option value="h3">H3</option>
                <option value="h4">H4</option>
                <option value="h5">H5</option>
                <option value="h6">H6</option>
            </select>`;
        $targetToolbar.append(headerSelect);
        const fontSizeSelect = `
            <select class="editor-font-size">
                <option value="">Font Size</option>
                <option value="10">10px</option>
                <option value="12">12px</option>
                <option value="14">14px</option>
                <option value="16">16px</option>
                <option value="18">18px</option>
                <option value="24">24px</option>
                <option value="36">36px</option>
                <option value="48">48px</option>
                <option value="72">72px</option>
            </select>`;
        $targetToolbar.append(fontSizeSelect);
        settings.customModules.forEach(module => {
            if (module.button) {
                const $btn = $(module.button);
                $btn.attr('data-module', module.name);
                $targetToolbar.append($btn);
            }
        });

        // Обработчики для селектов этого тулбара
        $targetToolbar.find('.editor-header').on('change', function() {
            const header = $(this).val();
            restoreSelection();
            if (header) {
                applyHeader(header);
            } else {
                document.execCommand('formatBlock', false, 'p');
            }
            updateToolbarState();
        });
        $targetToolbar.find('.editor-font-size').on('change', function() {
            const size = $(this).val();
            restoreSelection();
            if (size) {
                applyFontSize(size);
            }
            updateToolbarState();
        });
    }

    $.fn.addEditorModule = function(module) {
        if (module && module.name && typeof module.init === 'function') {
            const modules = $('body').data('celenaEditorModules') || [];
            modules.push(module);
            $('body').data('celenaEditorModules', modules);
        }
    };

})(jQuery);