(function() {
    'use strict';

    let highlightEnabled = false;
    let editorElement = null;
    let overlayElement = null;
    let styleElement = null;
    let hideStyleElement = null;
    let observer = null;
    let bodyObserver = null;
    let intervalTimer = null;
    let retryTimer = null;
    let resizeObserver = null;

    const COLORS = {
        keyword: '#0000FF',
        builtin: '#800080',
        function: '#800080',
        number: '#098658',
        string: '#A31515',
        comment: '#008000',
        default: '#000000'
    };

    const KEYWORDS = new Set([
        'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def',
        'del', 'elif', 'else', 'except', 'False', 'finally', 'for', 'from', 'global',
        'if', 'import', 'in', 'is', 'lambda', 'None', 'nonlocal', 'not', 'or', 'pass',
        'raise', 'return', 'True', 'try', 'while', 'with', 'yield'
    ]);

    const BUILTINS = new Set([
        'abs', 'all', 'any', 'bin', 'bool', 'chr', 'dict', 'dir', 'enumerate',
        'filter', 'float', 'format', 'help', 'hex', 'input', 'int', 'len', 'list',
        'map', 'max', 'min', 'oct', 'open', 'ord', 'pow', 'print', 'range',
        'repr', 'reversed', 'round', 'set', 'sorted', 'sum', 'tuple', 'type', 'zip'
    ]);

    let functionNames = new Set();
    let parseTimer = null;

    // ========== ДОБАВЛЕНО: текущий цвет текста ==========
    let currentTextColor = '#000000';

    function findEditor() {
        return document.querySelector('.cm-content[contenteditable="true"]');
    }

    function updateOverlayPosition() {
        if (!editorElement || !overlayElement) return;
        const container = editorElement.closest('.cm-editor');
        if (!container) return;
        const containerRect = container.getBoundingClientRect();
        const editorRect = editorElement.getBoundingClientRect();
        const top = editorRect.top - containerRect.top + container.scrollTop;
        const left = editorRect.left - containerRect.left + container.scrollLeft;
        overlayElement.style.top = top + 'px';
        overlayElement.style.left = left + 'px';
        overlayElement.style.width = editorRect.width + 'px';
        overlayElement.style.height = editorRect.height + 'px';
    }

    function createOverlay() {
        if (!editorElement) return;

        const container = editorElement.closest('.cm-editor');
        if (!container) return;

        const containerStyle = window.getComputedStyle(container);
        if (containerStyle.position === 'static') {
            container.style.position = 'relative';
        }

        const editorStyle = window.getComputedStyle(editorElement);

        overlayElement = document.createElement('div');
        overlayElement.id = 'python-syntax-overlay';
        // ========== ИЗМЕНЕНО: цвет берётся из currentTextColor ==========
        overlayElement.style.cssText = `
            position: absolute;
            pointer-events: none;
            background: transparent;
            white-space: pre-wrap;
            word-wrap: break-word;
            font-family: ${editorStyle.fontFamily};
            font-size: ${editorStyle.fontSize};
            line-height: ${editorStyle.lineHeight};
            tab-size: ${editorStyle.tabSize};
            padding: ${editorStyle.padding};
            margin: 0;
            border: none;
            overflow: hidden;
            color: ${currentTextColor};
            z-index: 5;
        `;

        container.appendChild(overlayElement);
        updateOverlayPosition();

        if (!styleElement) {
            styleElement = document.createElement('style');
            styleElement.id = 'python-syntax-styles';
            styleElement.textContent = `
                .python-syn-keyword { color: ${COLORS.keyword}; }
                .python-syn-builtin { color: ${COLORS.builtin}; }
                .python-syn-function { color: ${COLORS.function}; }
                .python-syn-number { color: ${COLORS.number}; }
                .python-syn-string { color: ${COLORS.string}; }
                .python-syn-comment { color: ${COLORS.comment}; font-style: italic; }
            `;
            document.head.appendChild(styleElement);
        }

        editorElement.addEventListener('scroll', syncScroll);
        window.addEventListener('resize', updateOverlayPosition);

        if (!resizeObserver) {
            resizeObserver = new ResizeObserver(() => {
                updateOverlayPosition();
            });
            resizeObserver.observe(container);
            resizeObserver.observe(editorElement);
        }
    }

    function collectFunctionNames(code) {
        const lines = code.split('\n');
        const funcs = new Set();
        for (let line of lines) {
            const match = line.match(/\bdef\s+([a-zA-Z_][a-zA-Z0-9_]*)/);
            if (match) funcs.add(match[1]);
        }
        return funcs;
    }

    function refreshFunctionNames() {
        if (!editorElement) return;
        const code = editorElement.textContent;
        functionNames = collectFunctionNames(code);
    }

    function scheduleParse() {
        if (parseTimer) clearTimeout(parseTimer);
        parseTimer = setTimeout(() => {
            refreshFunctionNames();
            updateHighlight();
            parseTimer = null;
        }, 300);
    }

    function tokenizeLine(line) {
        const tokens = [];
        let i = 0;
        const n = line.length;

        while (i < n) {
            const ch = line[i];

            if (/\s/.test(ch)) {
                let start = i;
                while (i < n && /\s/.test(line[i])) i++;
                tokens.push({ type: 'whitespace', text: line.slice(start, i) });
                continue;
            }

            if (ch === '#') {
                let start = i;
                while (i < n && line[i] !== '\n') i++;
                tokens.push({ type: 'comment', text: line.slice(start, i) });
                continue;
            }

            if (ch === '"' || ch === "'") {
                const quote = ch;
                let start = i;
                i++;
                while (i < n) {
                    if (line[i] === '\\') { i += 2; continue; }
                    if (line[i] === quote) { i++; break; }
                    i++;
                }
                tokens.push({ type: 'string', text: line.slice(start, i) });
                continue;
            }

            if (/[0-9]/.test(ch)) {
                let start = i;
                while (i < n && /[0-9.]/.test(line[i])) i++;
                tokens.push({ type: 'number', text: line.slice(start, i) });
                continue;
            }

            if (/[a-zA-Z_]/.test(ch)) {
                let start = i;
                while (i < n && /[a-zA-Z0-9_]/.test(line[i])) i++;
                const word = line.slice(start, i);
                if (KEYWORDS.has(word)) {
                    tokens.push({ type: 'keyword', text: word });
                } else if (BUILTINS.has(word) || functionNames.has(word)) {
                    tokens.push({ type: 'function', text: word });
                } else {
                    tokens.push({ type: 'identifier', text: word });
                }
                continue;
            }

            tokens.push({ type: 'other', text: ch });
            i++;
        }
        return tokens;
    }

    function lineToHtml(line) {
        const tokens = tokenizeLine(line);
        let html = '';
        tokens.forEach(token => {
            switch (token.type) {
                case 'keyword':
                    html += `<span class="python-syn-keyword">${escapeHtml(token.text)}</span>`;
                    break;
                case 'function':
                    html += `<span class="python-syn-function">${escapeHtml(token.text)}</span>`;
                    break;
                case 'number':
                    html += `<span class="python-syn-number">${escapeHtml(token.text)}</span>`;
                    break;
                case 'string':
                    html += `<span class="python-syn-string">${escapeHtml(token.text)}</span>`;
                    break;
                case 'comment':
                    html += `<span class="python-syn-comment">${escapeHtml(token.text)}</span>`;
                    break;
                default:
                    html += escapeHtml(token.text);
            }
        });
        return html;
    }

    function escapeHtml(text) {
        return text.replace(/[&<>"]/g, function(m) {
            if (m === '&') return '&amp;';
            if (m === '<') return '&lt;';
            if (m === '>') return '&gt;';
            if (m === '"') return '&quot;';
            return m;
        });
    }

    function updateHighlight() {
        if (!highlightEnabled || !editorElement || !overlayElement) return;
        const lines = editorElement.querySelectorAll(':scope > div.cm-line');
        let html = '';
        for (let line of lines) {
            const text = line.innerText || '';
            html += `<div class="cm-line">${lineToHtml(text)}</div>`;
        }
        overlayElement.innerHTML = html;
        updateOverlayPosition();
    }

    function syncScroll() {
        if (!editorElement || !overlayElement) return;
        overlayElement.scrollTop = editorElement.scrollTop;
        overlayElement.scrollLeft = editorElement.scrollLeft;
        updateOverlayPosition();
    }

    // ========== ДОБАВЛЕНО: обновление цвета текста в оверлее ==========
    function updateOverlayTextColor(color) {
        currentTextColor = color;
        if (overlayElement) {
            overlayElement.style.color = color;
            updateHighlight(); // перерисовка для применения цвета к токенам без класса
        }
    }

    function enableHighlight() {
        if (highlightEnabled) return;

        const newEditor = findEditor();
        if (!newEditor) {
            if (!retryTimer) {
                retryTimer = setTimeout(() => enableHighlight(), 500);
            }
            return;
        }

        if (editorElement !== newEditor) {
            editorElement = newEditor;
        }

        // Загружаем сохранённый цвет текста перед созданием оверлея
        if (window.loadTextColor) {
            currentTextColor = window.loadTextColor();
        } else {
            currentTextColor = '#000000';
        }

        highlightEnabled = true;
        window.highlightEnabled = true; // делаем доступным для других модулей
        createOverlay();
        if (!overlayElement) return;

        if (!hideStyleElement) {
            hideStyleElement = document.createElement('style');
            hideStyleElement.id = 'syntax-hide-text-style';
            hideStyleElement.textContent = `
                .cm-content {
                    color: transparent !important;
                }
            `;
            document.head.appendChild(hideStyleElement);
        }

        refreshFunctionNames();
        updateHighlight();

        editorElement.addEventListener('input', updateHighlight);
        editorElement.addEventListener('scroll', syncScroll);
        editorElement.addEventListener('input', scheduleParse);

        if (observer) observer.disconnect();
        observer = new MutationObserver(() => {
            updateHighlight();
        });
        observer.observe(editorElement, { childList: true, subtree: true, characterData: true });

        localStorage.setItem('syntaxHighlightEnabled', 'true');
    }

    function disableHighlight() {
        if (!highlightEnabled) return;
        highlightEnabled = false;
        window.highlightEnabled = false;

        if (hideStyleElement) {
            hideStyleElement.remove();
            hideStyleElement = null;
        }

        if (editorElement) {
            editorElement.removeEventListener('input', updateHighlight);
            editorElement.removeEventListener('scroll', syncScroll);
            editorElement.removeEventListener('input', scheduleParse);
            window.removeEventListener('resize', updateOverlayPosition);
        }
        if (resizeObserver) {
            resizeObserver.disconnect();
            resizeObserver = null;
        }
        if (observer) {
            observer.disconnect();
            observer = null;
        }
        if (overlayElement) {
            overlayElement.remove();
            overlayElement = null;
        }
        if (retryTimer) {
            clearTimeout(retryTimer);
            retryTimer = null;
        }
        localStorage.setItem('syntaxHighlightEnabled', 'false');
    }

    function loadHighlightState() {
        return localStorage.getItem('syntaxHighlightEnabled') === 'true';
    }

    function updateOverlayStyles() {
        if (!highlightEnabled || !editorElement || !overlayElement) return;
        const editorStyle = window.getComputedStyle(editorElement);
        overlayElement.style.fontFamily = editorStyle.fontFamily;
        overlayElement.style.fontSize = editorStyle.fontSize;
        overlayElement.style.lineHeight = editorStyle.lineHeight;
        // Если цвет текста изменился извне – обновляем
        const savedColor = window.loadTextColor ? window.loadTextColor() : '#000000';
        if (savedColor !== currentTextColor) {
            updateOverlayTextColor(savedColor);
        } else {
            updateHighlight();
        }
        updateOverlayPosition();
    }

    function initHighlight() {
        if (loadHighlightState()) {
            enableHighlight();
        }

        if (!bodyObserver) {
            bodyObserver = new MutationObserver(() => {
                if (!loadHighlightState()) return;
                const newEditor = findEditor();
                if (newEditor !== editorElement) {
                    disableHighlight();
                    enableHighlight();
                }
            });
            bodyObserver.observe(document.body, { childList: true, subtree: true });
        }

        if (!intervalTimer) {
            intervalTimer = setInterval(() => {
                if (loadHighlightState()) {
                    if (!highlightEnabled || !editorElement || !overlayElement) {
                        enableHighlight();
                    } else {
                        updateOverlayPosition();
                    }
                } else {
                    if (highlightEnabled) disableHighlight();
                }
            }, 2000);
        }
    }

    window.enableHighlight = enableHighlight;
    window.disableHighlight = disableHighlight;
    window.loadHighlightState = loadHighlightState;
    window.initHighlight = initHighlight;
    window.updateOverlayStyles = updateOverlayStyles;
    window.updateOverlayTextColor = updateOverlayTextColor;
})();