(function () {
    var textarea = document.getElementById('editor');
    if (!textarea) return;

    var form = textarea.closest('form');

    // --- DOM helpers ---

    function wrap(before, after, placeholder) {
        var start = textarea.selectionStart;
        var end = textarea.selectionEnd;
        var selected = textarea.value.slice(start, end) || placeholder;
        var replacement = before + selected + after;
        textarea.value = textarea.value.slice(0, start) + replacement + textarea.value.slice(end);
        if (selected === placeholder) {
            textarea.selectionStart = start + before.length;
            textarea.selectionEnd = start + before.length + placeholder.length;
        } else {
            textarea.selectionStart = start + replacement.length;
            textarea.selectionEnd = start + replacement.length;
        }
        textarea.focus();
    }

    function linePrefix(prefix) {
        var start = textarea.selectionStart;
        var lineStart = textarea.value.lastIndexOf('\n', start - 1) + 1;
        textarea.value = textarea.value.slice(0, lineStart) + prefix + textarea.value.slice(lineStart);
        textarea.selectionStart = textarea.selectionEnd = start + prefix.length;
        textarea.focus();
    }

    function insertAtCursor(s) {
        var start = textarea.selectionStart;
        var end = textarea.selectionEnd;
        textarea.value = textarea.value.slice(0, start) + s + textarea.value.slice(end);
        textarea.selectionStart = textarea.selectionEnd = start + s.length;
        textarea.dispatchEvent(new Event('input'));
        textarea.focus();
    }

    function applyResult(result) {
        textarea.value = result.text;
        textarea.selectionStart = textarea.selectionEnd = result.cursor;
        textarea.dispatchEvent(new Event('input'));
        textarea.focus();
    }

    function applyTableOp(fn, arg) {
        var result = arg !== undefined
            ? fn(textarea.value, textarea.selectionStart, arg)
            : fn(textarea.value, textarea.selectionStart);
        if (result) applyResult(result);
    }

    // --- Actions ---

    var T = EditorTables;
    var L = EditorLists;
    var D = EditorDates;
    var M = EditorMovie;

    var actions = {
        save:           function () { form.submit(); },
        bold:           function () { wrap('**', '**', 'bold text'); },
        italic:         function () { wrap('*', '*', 'italic text'); },
        h1:             function () { linePrefix('# '); },
        h2:             function () { linePrefix('## '); },
        h3:             function () { linePrefix('### '); },
        code:           function () { wrap('`', '`', 'code'); },
        codeblock:      function () { wrap('```\n', '\n```', 'code'); },
        quote:          function () { linePrefix('> '); },
        link:           function () { wrap('[', '](url)', 'link text'); },
        wikilink:       function () {
            var sel = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
            openTreePicker({
                title: 'Insert link',
                mode: 'any',
                initialPath: '/',
                confirmLabel: 'INSERT',
                onSelect: function (path, kind) {
                    if (kind === 'folder') {
                        insertAtCursor(sel ? '[[' + path + '|' + sel + ']]' : '[[' + path + ']]');
                    } else {
                        var name = path.split('/').pop();
                        insertAtCursor('[' + (sel || name) + '](' + path + ')');
                    }
                }
            });
        },
        ul:             function () { linePrefix('- '); },
        ol:             function () { linePrefix('1. '); },
        hr:             function () { wrap('\n\n---\n\n', '', ''); },
        fmttable:       function () { applyTableOp(T.formatTableText); },
        tblalignleft:   function () { applyTableOp(T.setColumnAlignment, 'left'); },
        tblaligncenter: function () { applyTableOp(T.setColumnAlignment, 'center'); },
        tblalignright:  function () { applyTableOp(T.setColumnAlignment, 'right'); },
        tblinsertcol:   function () { applyTableOp(T.insertColumn); },
        tbldeletecol:   function () { applyTableOp(T.deleteColumn); },
        tblinsertrow:   function () { applyTableOp(T.insertRow); },
        tbldeleterow:   function () { applyTableOp(T.deleteRow); },
        dateiso:        function () { insertAtCursor(D.isoDate()); },
        datelong:       function () { insertAtCursor(D.longDate()); },
        movie:          function () { M.run(textarea); },
    };

    // --- Keyboard shortcut registration ---

    var keyMap = {};
    document.querySelectorAll('[data-action]').forEach(function (btn) {
        btn.addEventListener('click', function () {
            var action = actions[btn.dataset.action];
            if (action) action();
        });
        if (btn.dataset.key) {
            keyMap[btn.dataset.key] = actions[btn.dataset.action];
        }
    });

    keyMap['T'] = actions.fmttable;
    keyMap['D'] = actions.dateiso;
    keyMap['W'] = actions.datelong;

    document.addEventListener('keydown', function (e) {
        if (!e.altKey || !e.shiftKey) return;
        // Shift+digit produces a layout-dependent character in e.key (e.g. "!"
        // on US, "!" on DE), so fall back to e.code for digit rows.
        var key = /^Digit[0-9]$/.test(e.code) ? e.code.slice(5) : e.key;
        var action = keyMap[key];
        if (action) {
            e.preventDefault();
            action();
        }
    });

    // --- Textarea key handling ---

    textarea.addEventListener('keydown', function (e) {
        if (e.key === 'Delete' && e.shiftKey) {
            var result = T.deleteRow(textarea.value, textarea.selectionStart)
                      || L.deleteOrderedLine(textarea.value, textarea.selectionStart);
            if (!result) return;
            e.preventDefault();
            applyResult(result);
            return;
        }
        if (e.key === 'Enter' && e.shiftKey) {
            var result = T.insertRowBelow(textarea.value, textarea.selectionStart);
            if (!result) return;
            e.preventDefault();
            applyResult(result);
            return;
        }
        if (e.key !== 'Enter') return;
        var result = L.handleEnterKey(textarea.value, textarea.selectionStart);
        if (!result) return;
        e.preventDefault();
        applyResult(result);
    });

    // --- Dropdown helper ---

    var openMenus = [];

    function makeDropdown(triggerBtn, items) {
        var menu = document.createElement('div');
        menu.className = 'dropdown-menu';
        items.forEach(function (item) {
            var btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'btn btn-tool dropdown-item';
            btn.textContent = item.label;
            btn.addEventListener('mousedown', function (e) {
                e.preventDefault();
                actions[item.action]();
                menu.classList.remove('is-open');
            });
            menu.appendChild(btn);
        });
        triggerBtn.appendChild(menu);
        openMenus.push(menu);

        triggerBtn.addEventListener('click', function (e) {
            if (e.target !== triggerBtn) return;
            var wasOpen = menu.classList.contains('is-open');
            openMenus.forEach(function (m) { m.classList.remove('is-open'); });
            if (!wasOpen) menu.classList.add('is-open');
        });
    }

    document.addEventListener('click', function (e) {
        var insideAny = openMenus.some(function (m) {
            return m.parentElement && m.parentElement.contains(e.target);
        });
        if (!insideAny) openMenus.forEach(function (m) { m.classList.remove('is-open'); });
    });
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape') openMenus.forEach(function (m) { m.classList.remove('is-open'); });
    });

    // --- Table dropdown ---

    var tblDropBtn = document.querySelector('[data-action="tbldrop"]');
    if (tblDropBtn) {
        makeDropdown(tblDropBtn, [
            { label: 'Format table',  action: 'fmttable' },
            { label: 'Align left',    action: 'tblalignleft' },
            { label: 'Align center',  action: 'tblaligncenter' },
            { label: 'Align right',   action: 'tblalignright' },
            { label: 'Insert column', action: 'tblinsertcol' },
            { label: 'Delete column', action: 'tbldeletecol' },
            { label: 'Insert row',    action: 'tblinsertrow' },
            { label: 'Delete row',    action: 'tbldeleterow' },
        ]);
    }

    // --- Date dropdown ---

    var dateDropBtn = document.querySelector('[data-action="datedrop"]');
    if (dateDropBtn) {
        makeDropdown(dateDropBtn, [
            { label: 'YYYY-MM-DD',               action: 'dateiso' },
            { label: 'DE Long',                  action: 'datelong' },
        ]);
    }
})();
