// Detects the local datascape-companion via a /status probe and wires up
// the footer status icon, file-row click interception, and the "reveal in
// file manager" page action. All companion calls are best-effort: if the
// fetch fails the page falls back to default browser behavior.

(function () {
    var COMPANION_PORT = 17680;
    var COMPANION_BASE = 'http://127.0.0.1:' + COMPANION_PORT;
    var STATUS_TIMEOUT_MS = 1500;

    var state = { available: false, info: null };

    function wikiPathFromHref(href) {
        // href is the URL the wiki rendered for the listing item (e.g.
        // "/photos/2024/img.jpg"). Strip leading slash and decode so the
        // companion sees a relative wiki path matching its on-disk layout.
        try {
            var u = new URL(href, window.location.href);
            if (u.origin !== window.location.origin) return null;
            var p = u.pathname.replace(/^\/+/, '');
            return decodeURIComponent(p);
        } catch (_) {
            return null;
        }
    }

    function companionGET(path, params) {
        var qs = '';
        if (params) {
            var parts = [];
            for (var k in params) {
                parts.push(encodeURIComponent(k) + '=' + encodeURIComponent(params[k]));
            }
            qs = '?' + parts.join('&');
        }
        var ctrl = new AbortController();
        var timer = setTimeout(function () { ctrl.abort(); }, STATUS_TIMEOUT_MS);
        return fetch(COMPANION_BASE + path + qs, {
            method: 'GET',
            mode: 'cors',
            credentials: 'omit',
            signal: ctrl.signal
        }).finally(function () { clearTimeout(timer); });
    }

    function renderFlyout(menu) {
        menu.innerHTML = '';
        if (state.available) {
            var info = state.info || {};
            var name = info.name || 'datascape-companion';
            var ver = info.version ? ' v' + info.version : '';
            var head = document.createElement('div');
            head.className = 'panel-header';
            head.textContent = 'Companion';
            menu.appendChild(head);

            var label = document.createElement('div');
            label.className = 'companion-line';
            label.textContent = name + ver;
            menu.appendChild(label);

            var link = document.createElement('a');
            link.className = 'btn btn-block';
            link.href = COMPANION_BASE + '/config';
            link.target = '_blank';
            link.rel = 'noopener';
            link.textContent = 'Settings';
            menu.appendChild(link);
        } else {
            var head2 = document.createElement('div');
            head2.className = 'panel-header';
            head2.textContent = 'Companion not detected';
            menu.appendChild(head2);

            var msg = document.createElement('div');
            msg.className = 'companion-line muted';
            msg.textContent = 'Install the companion to open files locally.';
            menu.appendChild(msg);

            var win = document.createElement('a');
            win.className = 'btn btn-block';
            win.href = '/companion/download/windows';
            win.textContent = 'Download — Windows';
            menu.appendChild(win);

            var lin = document.createElement('a');
            lin.className = 'btn btn-block';
            lin.href = '/companion/download/linux';
            lin.textContent = 'Download — Linux';
            menu.appendChild(lin);
        }
    }

    function updateFooterIcon() {
        var wrap = document.querySelector('[data-companion-status]');
        if (!wrap) return;
        wrap.hidden = false;
        var btn = wrap.querySelector('.companion-icon');
        if (state.available) {
            btn.textContent = '●';
            btn.classList.add('companion-on');
            btn.classList.remove('companion-off');
            btn.title = 'Companion detected';
        } else {
            btn.textContent = '○';
            btn.classList.add('companion-off');
            btn.classList.remove('companion-on');
            btn.title = 'Companion not detected';
        }
        var menu = wrap.querySelector('.companion-flyout');
        renderFlyout(menu);
        if (typeof wireDropdown === 'function') wireDropdown(btn);
    }

    function wireFileLinks() {
        if (!state.available) return;
        document.addEventListener('click', function (e) {
            if (!e.target.closest) return;
            // Match every listing style: table rows expose the file link inside
            // a .list-item row; thumbnail tiles are bare a.thumb-tile anchors;
            // diary photo grids wrap each thumbnail in a .photo-grid anchor.
            // The left tree rail's file anchors (a.tree-file) join in too;
            // folder anchors there end in "/" and fall through to navigation.
            // Search file-result anchors join in too: page results end in "/"
            // and fall through to navigation, file results don't and open locally.
            var anchor = e.target.closest('.list-item a, a.thumb-tile, .photo-grid a, aside.tree-sidebar a.tree-file, .search-card a');
            if (!anchor) return;
            var item = anchor.closest('.list-item');
            // Only intercept the primary file link, and only for files (not folders).
            // Folders end with "/" — let the browser navigate normally.
            var path = (item && item.dataset.path) || anchor.getAttribute('href');
            if (!path || path.endsWith('/')) return;
            // Allow modified clicks (open in new tab, etc.) to pass through.
            if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
            var rel = wikiPathFromHref(path);
            if (rel === null) return;
            e.preventDefault();
            companionGET('/open-file', { path: rel }).catch(function () {
                // Fallback: navigate to the file (download / inline view).
                window.location.href = anchor.href;
            });
        });
    }

    function wireRevealButton() {
        if (!state.available) return;
        var btns = document.querySelectorAll('[data-companion-reveal]');
        btns.forEach(function (btn) {
            btn.hidden = false;
            btn.addEventListener('click', function () {
                var rel = wikiPathFromHref(window.location.pathname);
                if (rel === null) rel = '';
                companionGET('/open-folder', { path: rel }).catch(function () { });
            });
        });
    }

    function wireFileRevealButtons() {
        // Per-result "open location" buttons on the search page. Unlike the
        // page reveal button (which reveals window.location), each carries its
        // own file path so it reveals that specific file in its folder.
        if (!state.available) return;
        var btns = document.querySelectorAll('[data-companion-file-reveal]');
        btns.forEach(function (btn) {
            btn.hidden = false;
            btn.addEventListener('click', function () {
                var rel = btn.getAttribute('data-companion-file-reveal');
                if (!rel) return;
                companionGET('/open-folder', { path: rel }).catch(function () { });
            });
        });
    }

    function probeStatus() {
        return companionGET('/status').then(function (r) {
            if (!r.ok) throw new Error('status ' + r.status);
            return r.json();
        }).then(function (info) {
            state.available = true;
            state.info = info;
        }).catch(function () {
            state.available = false;
            state.info = null;
        });
    }

    function init() {
        probeStatus().then(function () {
            updateFooterIcon();
            wireFileLinks();
            wireRevealButton();
            wireFileRevealButtons();
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();
