/*
 * Copyright (C) 2017 Vsevolod Stakhov <vsevolod@highsecure.ru>
 */

/* global require */

define(["jquery", "app/common"],
    ($, common) => {
        "use strict";
        const ui = {};

        ui.getActions = function getActions() {
            common.query("actions", {
                success: function (data) {
                    $("#actionsFormField").empty();
                    const items = [];
                    $.each(data[0].data, (i, item) => {
                        const actionsOrder = ["greylist", "add header", "rewrite subject", "reject"];
                        const idx = actionsOrder.indexOf(item.action);
                        if (idx >= 0) {
                            items.push({
                                idx: idx,
                                html:
                                '<div class="form-group">' +
                                    '<label class="col-form-label col-md-2 float-start">' + item.action + "</label>" +
                                    '<div class="controls slider-controls col-md-10">' +
                                        '<input class="action-scores form-control" data-id="action" type="number" value="' +
                                          item.value + '">' +
                                    "</div>" +
                                "</div>"
                            });
                        }
                    });

                    items.sort((a, b) => a.idx - b.idx);

                    $("#actionsFormField").html(
                        items.map((e) => e.html).join(""));
                },
                server: common.getServer()
            });
        };

        ui.saveActions = function (server) {
            function descending(arr) {
                let desc = true;
                const filtered = arr.filter((el) => el !== null);
                for (let i = 0; i < filtered.length - 1; i++) {
                    if (filtered[i + 1] >= filtered[i]) {
                        desc = false;
                        break;
                    }
                }
                return desc;
            }

            const elts = (function () {
                const values = [];
                const inputs = $("#actionsForm :input[data-id=\"action\"]");
                // Rspamd order: [spam, rewrite_subject, probable_spam, greylist]
                values[0] = parseFloat(inputs[3].value);
                values[1] = parseFloat(inputs[2].value);
                values[2] = parseFloat(inputs[1].value);
                values[3] = parseFloat(inputs[0].value);

                return JSON.stringify(values);
            }());
            // String to array for comparison
            const eltsArray = JSON.parse(elts);
            if (eltsArray[0] < 0) {
                common.alertMessage("alert-modal alert-danger", "Spam can not be negative");
            } else if (eltsArray[1] < 0) {
                common.alertMessage("alert-modal alert-danger", "Rewrite subject can not be negative");
            } else if (eltsArray[2] < 0) {
                common.alertMessage("alert-modal alert-danger", "Probable spam can not be negative");
            } else if (eltsArray[3] < 0) {
                common.alertMessage("alert-modal alert-danger", "Greylist can not be negative");
            } else if (descending(eltsArray)) {
                common.query("saveactions", {
                    method: "POST",
                    params: {
                        data: elts,
                        dataType: "json"
                    },
                    server: server
                });
            } else {
                common.alertMessage("alert-modal alert-danger", "Incorrect order of actions thresholds");
            }
        };

        ui.getMaps = function () {
            const $listmaps = $("#listMaps");
            common.hide($listmaps.closest(".card"));
            common.query("maps", {
                success: function (json) {
                    const [{data}] = json;
                    const $tbody = $listmaps.children("tbody").empty();

                    $.each(data, (i, item) => {
                        const $td = $("<td>");

                        const badges = [
                            {text: "Not loaded", cls: "text-bg-warning", cond: !item.loaded},
                            {text: "Cached", cls: "text-bg-info", cond: item.cached},
                            {text: "Writable", cls: "text-bg-success", cond: !(item.editable === false || common.read_only)}
                        ];
                        badges.forEach((b) => {
                            if (b.cond) $td.append($(`<span class="badge me-1 ${b.cls}">${b.text}</span>`));
                        });

                        const $tr = $("<tr>").append($td).append($("<td>" + item.type + "</td>"));
                        if (!item.loaded) $tr.addClass("table-active opacity-50");

                        const $span = $('<span class="map-link">' + item.uri + "</span>").data("item", item);
                        $span.wrap("<td>").parent().appendTo($tr);
                        $("<td>" + item.description + "</td>").appendTo($tr);
                        $tr.appendTo($tbody);
                    });
                    common.show($listmaps.closest(".card"));
                },
                server: common.getServer()
            });
        };


        let jar = {};
        const editor = {
            advanced: {
                codejar: true,
                elt: "div",
                class: "editor language-clike",
                readonly_attr: {contenteditable: false},
            },
            basic: {
                elt: "textarea",
                class: "form-control map-textarea",
                readonly_attr: {readonly: true},
            }
        };
        let mode = "advanced";

        // Modal form for maps
        $(document).on("click", ".map-link", function () {
            const item = $(this).data("item");
            common.query("getmap", {
                headers: {
                    Map: item.map
                },
                success: function (data) {
                    // Highlighting a large amount of text is unresponsive
                    mode = (new Blob([data[0].data]).size > 5120) ? "basic" : $("input[name=editorMode]:checked").val();

                    $("#modalBody").empty();
                    $("<" + editor[mode].elt + ' id="editor" class="' + editor[mode].class + '" data-id="' + item.map +
                        '"></' + editor[mode].elt + ">").appendTo("#modalBody");

                    if (editor[mode].codejar) {
                        require(["codejar", "linenumbers", "prism"], (CodeJar, withLineNumbers, Prism) => {
                            jar = new CodeJar(
                                document.querySelector("#editor"),
                                withLineNumbers((el) => Prism.highlightElement(el))
                            );
                            jar.updateCode(data[0].data);
                        });
                    } else {
                        document.querySelector("#editor").innerHTML = common.escapeHTML(data[0].data);
                    }

                    let icon = "fa-pen-to-square";
                    if (item.editable === false || common.read_only) {
                        $("#editor").attr(editor[mode].readonly_attr);
                        icon = "fa-eye";
                        common.hide("#modalSaveGroup");
                    } else {
                        common.show("#modalSaveGroup");
                    }
                    $("#modalDialog .modal-header").find("[data-fa-i2svg]").addClass(icon);
                    $("#modalTitle").html(item.uri);

                    $("#modalDialog").modal("show");
                },
                errorMessage: "Cannot receive maps data",
                server: common.getServer()
            });
        });
        $("#modalDialog").on("hidden.bs.modal", () => {
            if (editor[mode].codejar && jar && typeof jar.destroy === "function") {
                jar.destroy();
                $(".codejar-wrap").remove();
            } else {
                $("#editor").remove();
            }
        });

        $("#saveActionsBtn").on("click", () => {
            ui.saveActions();
        });
        $("#saveActionsClusterBtn").on("click", () => {
            ui.saveActions("All SERVERS");
        });

        function saveMap(server) {
            common.query("savemap", {
                success: function () {
                    common.alertMessage("alert-success", "Map data successfully saved");
                    $("#modalDialog").modal("hide");
                },
                errorMessage: "Save map error",
                method: "POST",
                headers: {
                    Map: $("#editor").data("id"),
                },
                params: {
                    data: editor[mode].codejar ? jar.toString() : $("#editor").val(),
                    dataType: "text",
                },
                server: server
            });
        }
        $("#modalSave").on("click", () => {
            saveMap();
        });
        $("#modalSaveAll").on("click", () => {
            saveMap("All SERVERS");
        });

        return ui;
    });
