(function () {
    "use strict";

    var _ = cockpit.gettext;

    var HELPER = "/usr/sbin/edubuntu-installer-helper";
    var QUERY  = "/usr/share/cockpit/edubuntu-installer/query.py";

    var state = null;
    var initialPkgs = [];       // initial installed package names
    var initialGlobalRadio = ""; // initial global default choice
    var initialUserRadios = {};  // username -> initial choice

    /* ── Tab switching ─────────────────────────────────────────── */

    var tabLinks = document.querySelectorAll(".nav-tabs a[data-toggle=tab]");
    tabLinks.forEach(function (a) {
        a.addEventListener("click", function (ev) {
            ev.preventDefault();
            tabLinks.forEach(function (l) {
                l.parentElement.classList.remove("active");
            });
            document.querySelectorAll(".tab-pane").forEach(function (p) {
                p.classList.remove("active");
            });
            a.parentElement.classList.add("active");
            var target = a.getAttribute("href").substring(1);
            document.getElementById(target).classList.add("active");
        });
    });

    /* ── Toggle log ────────────────────────────────────────────── */

    var toggleLink = document.getElementById("toggle-log");
    var outputLog  = document.getElementById("output-log");
    toggleLink.addEventListener("click", function (ev) {
        ev.preventDefault();
        if (outputLog.style.display === "none") {
            outputLog.style.display = "";
            toggleLink.textContent = _("Hide details ▴");
        } else {
            outputLog.style.display = "none";
            toggleLink.textContent = _("Show details ▾");
        }
    });

    /* ── Rendering ─────────────────────────────────────────────── */

    function renderPackages() {
        var container = document.getElementById("pkg-list");
        container.innerHTML = "";
        state.packages.forEach(function (pkg) {
            var lbl = document.createElement("label");
            var cb  = document.createElement("input");
            cb.type = "checkbox";
            cb.value = pkg.name;
            cb.checked = pkg.installed;
            cb.addEventListener("change", checkChanges);
            lbl.appendChild(cb);
            var text = " " + pkg.name;
            if (pkg.description)
                text += "  \u2014  " + pkg.description;
            lbl.appendChild(document.createTextNode(text));
            container.appendChild(lbl);
        });
    }

    function renderRadioGroup(containerId, name, choices, selected) {
        var container = document.getElementById(containerId);
        container.innerHTML = "";
        container.classList.add("radio-group");
        choices.forEach(function (choice) {
            var lbl = document.createElement("label");
            var rb  = document.createElement("input");
            rb.type = "radio";
            rb.name = name;
            rb.value = choice;
            rb.checked = (choice === selected);
            rb.addEventListener("change", checkChanges);
            lbl.appendChild(rb);
            lbl.appendChild(document.createTextNode(" " + choice));
            container.appendChild(lbl);
        });
    }

    function renderGlobalSetup() {
        renderRadioGroup("global-radios", "global-default",
                         state.setup_choices, state.global_default);
    }

    function currentUserDefault() {
        var sel = document.getElementById("user-select");
        var uname = sel.value;
        if (!uname) return "";
        var u = state.users.find(function (u) { return u.username === uname; });
        return u ? u.age_group : state.setup_choices[state.setup_choices.length - 1];
    }

    function renderPerUserSetup() {
        var sel = document.getElementById("user-select");
        if (!sel.value) {
            document.getElementById("user-radios").innerHTML =
                "<p class='text-muted'>" + _("No non-administrator users found.") + "</p>";
            return;
        }
        renderRadioGroup("user-radios", "user-default",
                         state.setup_choices, currentUserDefault());
    }

    function populateUsers() {
        var sel = document.getElementById("user-select");
        sel.innerHTML = "";
        if (state.users.length === 0) {
            renderPerUserSetup();
            return;
        }
        state.users.forEach(function (u) {
            var opt = document.createElement("option");
            opt.value = u.username;
            opt.textContent = u.username;
            sel.appendChild(opt);
        });
        sel.addEventListener("change", function () {
            renderPerUserSetup();
            checkChanges();
        });
    }

    /* ── Data loading ──────────────────────────────────────────── */

    function loadState() {
        document.getElementById("loading").style.display = "";
        document.getElementById("content").style.display = "none";
        document.getElementById("error-bar").style.display = "none";
        document.getElementById("progress-panel").style.display = "none";

        cockpit.spawn(["python3", QUERY], { superuser: "try", err: "message" })
            .then(function (data) {
                state = JSON.parse(data);
                renderPackages();
                renderGlobalSetup();
                populateUsers();
                renderPerUserSetup();
                // Capture initial state
                initialPkgs = checkedPkgValues();
                initialGlobalRadio = state.global_default;
                state.users.forEach(function (u) {
                    initialUserRadios[u.username] = u.age_group;
                });
                document.getElementById("btn-apply").disabled = true;
                document.getElementById("loading").style.display = "none";
                document.getElementById("content").style.display = "";
            })
            .catch(function (err) {
                showError(_("Failed to load state: ") + err.message);
            });
    }

    /* ── Helpers ───────────────────────────────────────────────── */

    function selectedRadio(name) {
        var rb = document.querySelector("input[name='" + name + "']:checked");
        return rb ? rb.value : "";
    }

    function checkedPkgValues() {
        var cbs = document.getElementById("pkg-list")
                          .querySelectorAll("input[type=checkbox]:checked");
        var result = [];
        cbs.forEach(function (cb) { result.push(cb.value); });
        return result;
    }

    function arraysEqual(a, b) {
        if (a.length !== b.length) return false;
        var sa = a.slice().sort();
        var sb = b.slice().sort();
        for (var i = 0; i < sa.length; i++) {
            if (sa[i] !== sb[i]) return false;
        }
        return true;
    }

    function checkChanges() {
        var btn = document.getElementById("btn-apply");
        // Check packages
        if (!arraysEqual(checkedPkgValues(), initialPkgs)) {
            btn.disabled = false;
            return;
        }
        // Check global radio
        if (selectedRadio("global-default") !== initialGlobalRadio) {
            btn.disabled = false;
            return;
        }
        // Check per-user radio
        var sel = document.getElementById("user-select");
        if (sel.value && initialUserRadios[sel.value] !== undefined) {
            if (selectedRadio("user-default") !== initialUserRadios[sel.value]) {
                btn.disabled = false;
                return;
            }
        }
        btn.disabled = true;
    }

    function showError(msg) {
        document.getElementById("loading").style.display = "none";
        document.getElementById("error-text").textContent = msg;
        document.getElementById("error-bar").style.display = "";
    }

    function setProgress(show) {
        document.getElementById("progress-panel").style.display =
            show ? "" : "none";
        if (show) {
            outputLog.textContent = "";
            outputLog.style.display = "none";
            toggleLink.textContent = _("Show details ▾");
        }
    }

    function appendLog(text) {
        outputLog.textContent += text;
        outputLog.scrollTop = outputLog.scrollHeight;
    }

    function runStream(cmd, label) {
        setProgress(true);
        return new Promise(function (resolve, reject) {
            var proc = cockpit.spawn(cmd, {
                superuser: "require",
                err: "message",
            });
            proc.stream(function (data) { appendLog(data); });
            proc.then(function () {
                resolve(true);
            }).catch(function (err) {
                appendLog("\nError: " + err.message + "\n");
                reject(err);
            });
        });
    }

    /* ── Apply ─────────────────────────────────────────────────── */

    function applyChanges() {
        var btn = document.getElementById("btn-apply");
        btn.disabled = true;
        document.getElementById("status-msg").textContent = "";

        var chain = Promise.resolve();

        // Determine package changes
        var toInstall = [];
        var toRemove  = [];
        var cbs = document.getElementById("pkg-list")
                          .querySelectorAll("input[type=checkbox]");
        cbs.forEach(function (cb) {
            var pkg = state.packages.find(function (p) {
                return p.name === cb.value;
            });
            if (!pkg) return;
            if (cb.checked && !pkg.installed)
                toInstall.push(cb.value);
            else if (!cb.checked && pkg.installed)
                toRemove.push(cb.value);
        });

        // apt-get update if package changes pending
        if (toInstall.length || toRemove.length) {
            chain = chain.then(function () {
                return runStream([HELPER, "update"], _("Updating package cache…"));
            });
        }

        // install
        if (toInstall.length) {
            chain = chain.then(function () {
                return runStream(
                    [HELPER, "install"].concat(toInstall),
                    _("Installing packages…")
                );
            });
        }

        // remove
        if (toRemove.length) {
            chain = chain.then(function () {
                return runStream(
                    [HELPER, "autoremove"].concat(toRemove),
                    _("Removing packages…")
                );
            });
        }

        // global default
        var newGlobal = selectedRadio("global-default");
        if (newGlobal && newGlobal !== state.global_default) {
            chain = chain.then(function () {
                if (newGlobal === state.setup_choices[state.setup_choices.length - 1]) {
                    return cockpit.spawn([HELPER, "tertdefault"],
                        { superuser: "require", err: "message" });
                }
                // Look up the gschema override content by querying the
                // helper inline — the helper accepts content as arg.
                // We replicate the mapping here for the Cockpit module.
                return cockpit.spawn(
                    ["python3", "/usr/share/cockpit/edubuntu-installer/apply-default.py",
                     newGlobal],
                    { superuser: "require", err: "message" }
                );
            });
        }

        // per-user default
        var sel = document.getElementById("user-select");
        var username = sel.value;
        if (username) {
            var newUser = selectedRadio("user-default");
            var curUser = currentUserDefault();
            if (newUser && newUser !== curUser) {
                chain = chain.then(function () {
                    if (newUser === state.setup_choices[state.setup_choices.length - 1]) {
                        return cockpit.spawn(
                            [HELPER, "usertertdefault", username],
                            { superuser: "require", err: "message" }
                        );
                    }
                    return cockpit.spawn(
                        ["python3",
                         "/usr/share/cockpit/edubuntu-installer/apply-default.py",
                         "--user", username, newUser],
                        { superuser: "require", err: "message" }
                    );
                });
            }
        }

        chain
            .then(function () {
                setProgress(false);
                document.getElementById("status-msg").textContent = _("Changes applied.");
                btn.disabled = false;
                loadState();
            })
            .catch(function (err) {
                showError(_("Apply failed: ") + err.message);
                btn.disabled = false;
            });
    }

    /* ── Wire buttons ──────────────────────────────────────────── */

    document.getElementById("btn-apply").addEventListener("click", applyChanges);
    document.getElementById("btn-reload").addEventListener("click", function () {
        document.getElementById("status-msg").textContent = "";
        loadState();
    });

    /* ── Bootstrap ─────────────────────────────────────────────── */

    loadState();
})();
