/* eslint-disable no-prototype-builtins */
function openRuleDetailsDialog(rule_result_id) { // eslint-disable-line no-unused-vars

    /*
     *DO NOT remove the aria-hidden="false" attribute from the following lines!
     *This attribute ensures that rule detail can be accessed by accessibility technologies such as screenreaders.
     */
    var closebutton = $('<button type="button" class="close btn btn-sm btn-default" data-dismiss="modal" aria-hidden="false" title="Close">&#x274c;</button>');
    var modal = $('<div id="detail-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="false"><div id="detail-modal-body" class="modal-body"></div></div>');

    $("body").prepend(modal);

    var clone = $("#rule-detail-" + rule_result_id).clone();
    clone.attr("id", "");
    clone.children(".panel-heading").append(closebutton);
    closebutton.css({ "float": "right" });
    closebutton.css({ "margin-top": "-=23px" });
    $("#detail-modal-body").append(clone);

    $('#detail-modal').on('hidden.bs.modal', function () {
        $("#detail-modal").remove();
    })
    $("#detail-modal").modal();

    return false;
}

function toggleRuleDisplay(checkbox) {
    var result = checkbox.value;

    if (checkbox.checked) {
        $(".rule-overview-leaf-" + result).removeClass("rule-result-filtered");
        $(".rule-detail-" + result).removeClass("rule-result-filtered");
    } else {
        $(".rule-overview-leaf-" + result).addClass("rule-result-filtered");
        $(".rule-detail-" + result).addClass("rule-result-filtered");
    }
    stripeTreeTable();
}

function toggleResultDetails(button) { // eslint-disable-line no-unused-vars
    var result_details = $("#result-details");

    if (result_details.is(":visible")) {
        result_details.hide();
        $(button).html("Show all result details");
    } else {
        result_details.show();
        $(button).html("Hide all result details");
    }

    return false;
}

function ruleSearchMatches(detail_leaf, keywords) {
    if (keywords.length == 0) {
        return true;
    }

    var match = true;
    var checked_keywords = detail_leaf.children(".keywords").text().toLowerCase();

    for (const keyword of keywords) {
        if (checked_keywords.indexOf(keyword.toLowerCase()) < 0) {
            match = false;
            break;
        }
    }

    return match;
}

function ruleSearch() { // eslint-disable-line no-unused-vars
    var search_input = $("#search-input").val();
    var keywords = search_input.split(/[\s,\.;]+/u);
    var matches = 0;

    $(".rule-detail").each(function () {
        // rule-detail-rrid, that's offset 12
        var rrid = $(this).attr("id").substring(12);

        var overview_leaf = $("#rule-overview-leaf-" + rrid);
        var detail_leaf = $(this);

        if (ruleSearchMatches(detail_leaf, keywords)) {
            overview_leaf.removeClass("search-no-match");
            detail_leaf.removeClass("search-no-match");
            matches += 1;
        } else {
            overview_leaf.addClass("search-no-match");
            detail_leaf.addClass("search-no-match");
        }
    });

    if (!search_input) {
        $("#search-matches").html("");
    } else if (matches > 0) {
        $("#search-matches").html(matches.toString() + " rules match.");
    } else {
        $("#search-matches").html("No rules match your search criteria!");
    }
}

var is_original = true;
var original_treetable = null;

$(document).ready(function () {
    $("#result-details").hide();
    $(".js-only").show();
    $(".form-group select").val("default");
    $(".toggle-rule-display").each(function () {
        toggleRuleDisplay(this);
    });
    original_treetable = $(".treetable").clone();
    $(".treetable").treetable({ "column": 0, "expandable": true, "clickableNodeNames": true, "initialState": "expanded", "indent": 0 });
    is_original = true;
    stripeTreeTable();
});

function resetTreetable() {
    if (!is_original) {
        $(".treetable").remove();
        $("#rule-overview").append(original_treetable.clone());
        $(".treetable").treetable({ "column": 0, "expandable": true, "clickableNodeNames": true, "initialState": "expanded", "indent": 0 });
        $(".toggle-rule-display").each(function () {
            toggleRuleDisplay(this);
        });
        is_original = true;
    }
}

function newGroupLine(key, group_name) {
    // ellipsize key in case it's too long
    var maxKeyLength = 24;
    if (key.length > maxKeyLength) {
        // eslint-disable-next-line no-param-reassign
        key = key.substring(0, maxKeyLength - 1) + "…";
    }

    return "<tr class=\"rule-overview-inner-node\" data-tt-id=\"" + group_name + "\">" +
        "<td colspan=\"3\"><small>" + key + "</small> = <strong>" + group_name + "</strong></td></tr>";
}

var KeysEnum = {
    "DEFAULT": "default",
    "SEVERITY": "severity",
    "RESULT": "result",
    "NIST": "NIST SP 800-53 ID",
    "DISA_CCI": "DISA CCI",
    "DISA_SRG": "DISA SRG",
    "DISA_STIG_ID": "DISA STIG ID",
    "PCI_DSS": "PCI DSS Requirement",
    "CIS": "CIS Recommendation"
};

/* This function returns an array of target groups indentifiers */
function getTargetGroupsList(rule, key) {
    switch (key) {
        case KeysEnum.SEVERITY:
            var severity = rule.children(".rule-severity").text();
            return [severity];
        case KeysEnum.RESULT:
            var result = rule.children(".rule-result").text();
            return [result];
        default:
            try {
                var references = JSON.parse(rule.attr("data-references"));
                if (!references.hasOwnProperty(key)) {
                    return ["unknown"];
                }
                return references[key];
            } catch (err) {
                return ["unknown"];
            }
    }
}

function sortGroups(groups, key) {
    switch (key) {
        case KeysEnum.SEVERITY:
            return [
                "high",
                "medium",
                "low"
            ];
        case KeysEnum.RESULT:
            return groups.sort();
        default:
            return groups.sort(function (a, b) {
                var a_parts = a.split(/[.()-]/u);
                var b_parts = b.split(/[.()-]/u);
                var result = 0;
                var min_length = Math.min(a_parts.length, b_parts.length);
                var number = /^[1-9][0-9]*$/u;
                // eslint-disable-next-line no-plusplus
                for (var i = 0; i < min_length && result == 0; i++) {
                    if (a_parts[i].match(number) === null || a_parts[i].match(number) === null) {
                        result = a_parts[i].localeCompare(b_parts[i]);
                    } else {
                        result = parseInt(a_parts[i], 10) - parseInt(b_parts[i], 10);
                    }
                }
                if (result == 0) {
                    result = a_parts.length - b_parts.length;
                }
                return result;
            });
    }
}

function groupRulesBy(key) { // eslint-disable-line no-unused-vars

    /*
     * We must reset the treetable and process grouping upon the original
     * table to avoid unwanted duplicties in new table.
     */
    resetTreetable();
    if (key == KeysEnum.DEFAULT) {
        return;
    }

    /* Browse the rules and sort them into groups */
    var lines = {};
    $(".rule-overview-leaf").each(function () {
        $(this).children("td:first").css("padding-left", "0px");
        var id = $(this).attr("data-tt-id");
        var target_groups = getTargetGroupsList($(this), key);
        // eslint-disable-next-line no-plusplus
        for (var i = 0; i < target_groups.length; i++) {
            var target_group = target_groups[i];
            if (!lines.hasOwnProperty(target_group)) {

                /* Create a new group */
                lines[target_group] = [newGroupLine(key, target_group)];
            }
            var clone = $(this).clone();
            clone.attr("data-tt-id", id + "copy" + i);
            clone.attr("data-tt-parent-id", target_group);
            var new_line = clone.wrap("<div>").parent().html();
            lines[target_group].push(new_line);
        }
    });

    /* Remove old treetable and replace it with a new one */
    $(".treetable").remove();
    var groups = sortGroups(Object.keys(lines), key);
    var html_text = "";
    for (const group of groups) {
        html_text += lines[group].join("\n");
    }
    var new_table = "<table class=\"treetable table table-bordered\"><thead><tr><th>Group</th> <th style=\"width: 120px; text-align: center\">Severity</th><th style=\"width: 120px; text-align: center\">Result</th></tr></thead><tbody>" + html_text + "</tbody></table>";
    $("#rule-overview").append(new_table);
    is_original = false;
    $(".treetable").treetable({
        "column": 0,
        "expandable": true,
        "clickableNodeNames": true,
        "initialState": "expanded",
        "indent": 0
    });
    stripeTreeTable();
}

function stripeTreeTable() {
    var rows = $(".rule-overview-leaf:not(.rule-result-filtered)");
    var even = false;
    $(rows).each(function () {
        $(this).css("background-color", even ? "#F9F9F9" : "inherit");
        even = !even;
    });
}
