<script>
    const keyImportButton = $("#key-import-btn");
    const packageAddButton = $("#package-add-btn");
    const packageRebuildButton = $("#package-rebuild-btn");
    const packageRemoveButton = $("#package-remove-btn");
    const packageUpdateButton = $("#package-update-btn");

    const table = $("#packages");
    table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
        packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
    });
    table.on("click-row.bs.table", (self, data, row, cell) => {
        if (0 === cell || "base" === cell) {
            const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
            table.bootstrapTable(method, {field: "id", values: [data.id]});
        } else showLogs(data.id);
    });
    table.on("created-controls.bs.table", () => {
        const pickerInput = $(".bootstrap-table-filter-control-timestamp");
        pickerInput.daterangepicker({
            autoUpdateInput: false,
            locale: {
                cancelLabel: "Clear",
            },
        });

        pickerInput.on("apply.daterangepicker", (event, picker) => {
            pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
            table.bootstrapTable("triggerSearch");
        });

        pickerInput.on("cancel.daterangepicker", () => {
            pickerInput.val("");
            table.bootstrapTable("triggerSearch");
        });
    });

    const repositoryBadge = $("#badge-repository");
    const statusBadge = $("#badge-status");
    const versionBadge = $("#badge-version");

    function doPackageAction(uri, packages, successText, failureText) {
        $.ajax({
            url: uri,
            data: JSON.stringify({packages: packages}),
            type: "POST",
            contentType: "application/json",
            success: _ => {
                const message = successText(packages.join(", "));
                showSuccess("Success", message);
            },
            error: (jqXHR, _, errorThrown) => {
                showFailure("Action failed", failureText, jqXHR, errorThrown);
            },
        });
    }

    function getSelection() {
        return table.bootstrapTable("getSelections").map(row => row.id);
    }

    function removePackages() {
        const onSuccess = update => `Packages ${update} have been removed`;
        const onFailure = error => `Could not remove packages: ${error}`;
        doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure);
    }

    function updatePackages() {
        const currentSelection = getSelection();
        const [url, onSuccess] = currentSelection.length === 0
            ? ["/api/v1/service/update", _ => "Repository update has been run"]
            : ["/api/v1/service/add", update => `Run update for packages ${update}`];
        const onFailure = error => `Packages update failed: ${error}`;
        doPackageAction(url, currentSelection, onSuccess, onFailure);
    }

    function hideControls(hidden) {
        keyImportButton.attr("hidden", hidden);
        packageAddButton.attr("hidden", hidden);
        packageRebuildButton.attr("hidden", hidden);
        packageRemoveButton.attr("hidden", hidden);
        packageUpdateButton.attr("hidden", hidden);
    }

    function reload() {
        table.bootstrapTable("showLoading");

        const badgeClass = status => {
            if (status === "pending") return "btn-outline-warning";
            if (status === "building") return "btn-outline-warning";
            if (status === "failed") return "btn-outline-danger";
            if (status === "success") return "btn-outline-success";
            return "btn-outline-secondary";
        };

        $.ajax({
            url: "/api/v1/packages",
            type: "GET",
            dataType: "json",
            success: response => {
                const extractListProperties = (description, property) => {
                    return Object.values(description.packages)
                        .map(pkg => pkg[property])
                        .reduce((left, right) => left.concat(right), []);
                };
                const listToTable = data => {
                    return Array.from(new Set(data))
                        .sort()
                        .map(entry => safe(entry))
                        .join("<br>");
                };

                const payload = response.map(description => {
                    const package_base = description.package.base;
                    const web_url = description.package.remote.web_url;
                    return {
                        id: package_base,
                        base: web_url ? `<a href="${safe(web_url)}" title="${safe(package_base)}">${safe(package_base)}</a>` : safe(package_base),
                        version: safe(description.package.version),
                        packager: description.package.packager ? safe(description.package.packager) : "",
                        packages: listToTable(Object.keys(description.package.packages)),
                        groups: listToTable(extractListProperties(description.package, "groups")),
                        licenses: listToTable(extractListProperties(description.package, "licenses")),
                        timestamp: new Date(1000 * description.status.timestamp).toISOString(),
                        status: description.status.status,
                    };
                });

                table.bootstrapTable("load", payload);
                table.bootstrapTable("uncheckAll");
                table.bootstrapTable("hideLoading");
                hideControls(false);
            },
            error: (jqXHR, _, errorThrown) => {
                if ((jqXHR.status === 401) || (jqXHR.status === 403)) {
                    // authorization error
                    const text = "In order to see statuses you must login first.";
                    table.find("tr.unauthorized").remove();
                    table.find("tbody").append(`<tr class="unauthorized"><td colspan="100%">${safe(text)}</td></tr>`);
                    table.bootstrapTable("hideLoading");
                } else {
                    // other errors
                    const message = error => `Could not load list of packages: ${error}`;
                    showFailure("Load failure", message, jqXHR, errorThrown);
                }
                hideControls(true);
            },
        });

        $.ajax({
            url: "/api/v1/status",
            type: "GET",
            dataType: "json",
            success: response => {
                repositoryBadge.text(`${response.repository} ${response.architecture}`);
                versionBadge.html(`<i class="bi bi-github"></i> ahriman ${safe(response.version)}`);

                statusBadge
                    .popover("dispose")
                    .attr("data-bs-content", `${response.status.status} at ${new Date(1000 * response.status.timestamp).toISOString()}`)
                    .popover();
                statusBadge.removeClass();
                statusBadge.addClass("btn");
                statusBadge.addClass(badgeClass(response.status.status));
            },
        });
    }

    function statusFormat(value) {
        const cellClass = status => {
            if (status === "pending") return "table-warning";
            if (status === "building") return "table-warning";
            if (status === "failed") return "table-danger";
            if (status === "success") return "table-success";
            return "table-secondary";
        };
        return {classes: cellClass(value)};
    }

    function filterListGroups() {
        return extractDataList(table.bootstrapTable("getData"), "groups");
    }

    function filterListLicenses() {
        return extractDataList(table.bootstrapTable("getData"), "licenses");
    }

    function filterListPackagers() {
        return extractDataList(table.bootstrapTable("getData"), "packager");
    }

    $(() => {
        table.bootstrapTable({});
        statusBadge.popover();
        reload();
    });
</script>