{{/*
This file is part of SystemTestPortal.
Copyright (C) 2017  Institute of Software Technology, University of Stuttgart

SystemTestPortal is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SystemTestPortal is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SystemTestPortal.  If not, see <http://www.gnu.org/licenses/>.
*/}}

$.getScript("/static/js/project/project-tabs.js");
$.getScript("/static/js/util/ajax.js");
$.getScript("/static/js/project/testprotocols.js");

//Initialize variables with id's
var dropdown = "#versions-dropdown-menu";
var dashboardVariantHeader = "#variantNames";
var dashboardContent = "#dashboard-content";
var dashboardToggle = "#dashboardToggle";

/**
 * Initialize an on change listener and runs refreshDashboard with the correct boolean dependent on the toggle state.
 *
 * @param id the id of the element that should be listened
 */
function onChangeInit(id) {
    $(id).on("change", function () {
        if ($(dashboardToggle).prop('checked')){
            refreshDashboard(casesDashboardElements, versions, variants, $(dropdown)[0].selectedIndex, true);
        } else {
            refreshDashboard(sequencesDashboardElements, versions, variants, $(dropdown)[0].selectedIndex, false);
        }
    });
}

/**
 * Loads the dashboard with cases or sequences, dependent on the state of the toggle.
 */
$(function () {
    onChangeInit(dashboardToggle);
});

/**
 * Loads the dashboard after changing variants in the dropdown.
 */
$(function () {
    onChangeInit(dropdown);
});

/**
 * Fills the dropdown with all variants of the project
 * @param variants an array with all variants of the project
 */
function fillDropdown(variants) {
    variants.forEach(function (element) {

        let el = document.createElement("option");
        el.textContent = element.Name;
        $(dropdown).append(el);
    });
}

/**
 * Refreshes the dashboard with new results after switching between variants in the dropdown.
 *
 * @param dashboardElements elements of the Dashboard, can be cases or sequence dashboard elements.
 * @param versions all Versions of the project
 * @param variants all variants of the project
 * @param selectedIndex the selectedIndex of the variant dropdown
 * @param toggleState the state of the toggle between cases and sequences
 */
function refreshDashboard(dashboardElements, versions, variants, selectedIndex, toggleState) {
    changeDashboardVersionHeader(versions, toggleState);
    fillDashboardWithResults(variants, dashboardElements, selectedIndex, toggleState);
    $('[data-toggle="tooltip"]').tooltip();
}

/**
 * Loads a new Dashboard and selects the first entry of the variant dropdown.
 *
 * @param dashboardElements elements of the Dashboard, can be cases or sequence dashboard elements.
 * @param versions all Versions of the project
 * @param variants all variants of the project
 * @param toggleState the state of the toggle between cases and sequences
 */
function newSiteDashboard(dashboardElements, versions, variants, toggleState) {
    changeDashboardVersionHeader(versions, toggleState);
    fillDashboardWithResults(variants, dashboardElements, 0, toggleState);
}

/**
 * Changes the Header of the Dashboard, dependent on the dashboard toggle.
 *
 * @param versions all Versions of the project
 * @param toggleState the state of the toggle between cases and sequences
 */
function changeDashboardVersionHeader(versions, toggleState) {
    if (toggleState) {
        $(dashboardVariantHeader).html("<th>Test Cases</th>");
    } else {
        $(dashboardVariantHeader).html("<th>Test Sequences</th>");
    }

    versions.forEach(function (element) {
        let el = document.createElement("th");
        el.setAttribute("class", "text-center");
        el.textContent = element.Name;
        $(dashboardVariantHeader).append(el);
    });
}

/**
 * Fills the dashboard with cases/sequences and the correct results.
 *
 * @param variants all variants of the project
 * @param dashboardElements elements of the Dashboard, can be cases or sequence dashboard elements.
 * @param selectedIndex the selectedIndex of the variant dropdown
 * @param toggleState the state of the toggle between cases and sequences
 */
function fillDashboardWithResults(variants, dashboardElements, selectedIndex, toggleState) {
    const variant = variants[selectedIndex];
    let results = null;
    dashboardElements.forEach(function (element) {
        if (variant.Name === element.Variant.Name) {
            results = element.Results;
        }
    });

    $(dashboardContent).html("");

    createTable(results, toggleState);
}

/**
 * Creates a table with cases or sequences as lines.
 *
 * @param results results of the dashboard element, dependent on the selected variant
 * @param toggleState the state of the toggle between cases and sequences
 */
function createTable(results, toggleState) {
    results.forEach(function (result) {
        let protocols = result.Protocols;
        let dashboardLine = document.createElement("tr");
        //test objects are cases or sequences
        let testObject = document.createElement("td");
        let testObjectName;
        if (toggleState) {
            testObjectName = result.TestCase.Name.toString();
        } else {
            testObjectName = result.TestSequence.Name.toString();
        }

        testObject.setAttribute("class", "align-middle testCaseCell");
        testObject.setAttribute("id", testObjectName);
        testObject.textContent = testObjectName;
        if (toggleState) {
            testObject.onclick = onTestCaseClick;
        } else {
            testObject.onclick = onTestSequenceClick;
        }
        dashboardLine.appendChild(testObject);

        fillTableWithIcons(result, testObjectName, protocols, dashboardLine, toggleState);

        $(dashboardContent).append(dashboardLine);
    });
}

/**
 * Fills each line with the correct results
 *
 * @param result the result of the test case/sequence
 * @param testObjectName name of the test case/sequence
 * @param protocols
 * @param dashboardLine current line to fill
 */
function fillTableWithIcons(result, testObjectName, protocols, dashboardLine, toggleState) {
    let protocolIndex = 0;
    result.Results.forEach(function (result) {
        let el = document.createElement("td");
        let resultIcon;

        el.setAttribute("class", "text-center resultCaseCell");
        el.setAttribute("style", "font-size:1.5em;");
        el.setAttribute("id", testObjectName + protocolIndex.toString());
        //Adds click handler for different results
        if (result === 4) {
            resultIcon = initResultIcon(result, null);
            onTestCaseNotApplicableHandler(el, testObjectName);
            // if the test case is not applicable no protocol is sent
        } else if (protocols[protocolIndex].ProtocolNr === 0) { // required comparison to distinguish between "not assessed" and "not executed"
            resultIcon = initResultIcon(result, null);
            onTestResultClickHandler(el, testObjectName, null, toggleState);
            protocolIndex++; // not assessed sends empty protocol
        } else {
            resultIcon = initResultIcon(result, protocols[protocolIndex]);
            onTestResultClickHandler(el, testObjectName, protocols[protocolIndex], toggleState);
            protocolIndex++;
        }

        el.appendChild(resultIcon);

        dashboardLine.appendChild(el);
    });
}

/**
 * Initalize the result Icon, dependent on the result.
 *
 * @param result result of an test case/sequence
 * @param protocol
 * @returns {HTMLElement} the result Icon as HTML
 */
function initResultIcon_Sequences(result, protocol) {
    var resultIcon = document.createElement("i");
    resultIcon.setAttribute("aria-hidden", "true");
    resultIcon.setAttribute("data-toggle", "tooltip");
    resultIcon.setAttribute("data-placement", "bottom");
    if (result === 0) {
        resultIcon.setAttribute("class", "fa fa-times-circle text-secondary");
        resultIcon.setAttribute("title", "Test sequence not yet executed");
        if (protocol !== null) {
            resultIcon.setAttribute("class", "fa fa-question-circle text-secondary");
            initTooltip_Sequences(resultIcon, "Not assessed", protocol);
        }
        return resultIcon;
    }

    if (result === 1) {
        resultIcon.setAttribute("class", "fa fa-check-circle text-success");
        resultIcon.setAttribute("title", "Passed");
        initTooltip_Sequences(resultIcon, "Not assessed", protocol);
        return resultIcon;
    }

    if (result === 2) {
        resultIcon.setAttribute("class", "fa fa-exclamation-triangle text-warning");
        resultIcon.setAttribute("title", "Passed with comments");
        initTooltip_Sequences(resultIcon, "Not assessed", protocol);
        return resultIcon;
    }

    if (result === 3) {
        resultIcon.setAttribute("class", "fa fa-exclamation-circle text-danger");
        resultIcon.setAttribute("title", "Failed");
        initTooltip_Sequences(resultIcon, "Not assessed", protocol);
        return resultIcon;
    }

    if (result === 4) {
        resultIcon.setAttribute("class", "fa fa-minus text-secondary");
        resultIcon.setAttribute("title", "Test sequence is not applicable for this version");
        return resultIcon;
    }
}

function initResultIcon(result, protocol) {
    let resultIcon = document.createElement("i");
    resultIcon.setAttribute("aria-hidden", "true");
    resultIcon.setAttribute("data-toggle", "tooltip");
    resultIcon.setAttribute("data-placement", "bottom");

    if (result === 0) {
        resultIcon.setAttribute("class", "fa fa-times-circle text-secondary");
        resultIcon.setAttribute("title", "Test case not yet executed");
        if (protocol !== null) {
            resultIcon.setAttribute("class", "fa fa-question-circle text-secondary");
            initTooltip(resultIcon, "Not assessed", protocol);
        }
        return resultIcon;
    }

    if (result === 1) {
        resultIcon.setAttribute("class", "fa fa-check-circle text-success");
        resultIcon.setAttribute("title", "Passed");
        initTooltip(resultIcon, "Passed", protocol);
        return resultIcon;
    }

    if (result === 2) {
        resultIcon.setAttribute("class", "fa fa-exclamation-triangle text-warning");
        resultIcon.setAttribute("title", "Partially Successful");
        initTooltip(resultIcon, "Partially Successful", protocol);
        return resultIcon;
    }

    if (result === 3) {
        resultIcon.setAttribute("class", "fa fa-exclamation-circle text-danger");
        resultIcon.setAttribute("title", "Failed");
        initTooltip(resultIcon, "Failed", protocol);
        return resultIcon;
    }

    if (result === 4) {
        resultIcon.setAttribute("class", "fa fa-minus text-secondary");
        resultIcon.setAttribute("title", "Test case is not applicable for this version");
        return resultIcon;
    }
}

/**
 * OnClick listener for testcase cells
 *
 * @param event
 */
function onTestCaseClick(event) {
    $("#tabButtonDashboard").removeClass("active");
    $("#menuButtonDashboard").removeClass("active");

    //Testcase page
    $("#tabButtonTestCases").addClass("active");
    $("#menuButtonTestCases").addClass("active");
    let url = getProjectTabURL().toString().replace("dashboard", "testcases");
    url = url + "/" + event.target.id.toString();
    ajaxRequestFragment(event, url.toString(), "", "GET");
}

/**
 * Onclick handler for result cells
 *
 * @param element
 * @param testName
 * @param protocol
 * @param isCase
 */
function onTestResultClickHandler(element, testName, protocol, isCase) {
    element.addEventListener("click", function (event) {
        if (protocol != null) {
            $('body>.tooltip').remove();
            //Adds right tab highlighting
            $("#tabButtonDashboard").removeClass("active");
            $("#menuButtonDashboard").removeClass("active");
            $("#tabButtonProtocols").addClass("active");
            $("#menuButtonProtocols").addClass("active");

            //links to the test case protocol
            let url = getProjectTabURL().toString().replace("dashboard", "protocols");
            if (isCase) {
                url = url + "/testcases/" + testName;
            } else {
                url = url + "/testsequences/" + testName;
            }
            url = url + "/" + protocol.ProtocolNr.toString();
            ajaxRequestFragment(event, url.toString(), "", "GET");
        } else {
            //if no protocol exists, gives feedback to user
            window.alert("There is no protocol for test: " + testName);
        }
    });
}

/**
 * Shows alert for user if test case is not applicable for the version
 *
 * @param element
 * @param testName
 */
function onTestCaseNotApplicableHandler(element, testName) {
    element.addEventListener("click", function (event) {
        window.alert("Test: " + testName + " is not applicable for this version");
    });
}

/**
 * Shows a tooltip for resultIcons
 *
 * @param resultIcon
 * @param result
 * @param protocol
 * @param toggleState
 */
function initTooltip(resultIcon, result, protocol, toggleState) {
    const time = new Date(protocol.ExecutionDate).toLocaleString();
    let comment;
    if (toggleState) {
        if (protocol.Comment === "") {
            comment = "No comment"
        } else if (protocol.Comment.length > 50) {
            comment = protocol.Comment.substring(0, 49) + "...";
        } else {
            comment = protocol.Comment;
        }
        resultIcon.setAttribute("title", "Result: " + result + "\nTester: " + protocol.UserName.toString() + "\nComment: " + comment + "\nDate: " + time);
    } else {
        resultIcon.setAttribute("title", "Result: " + result + "\nTester: " + protocol.UserName.toString() + "\nDate: " + time);
    }
}

/**
 * Onclick listener for testsequence cells
 * @param event
 */
function onTestSequenceClick(event) {
    $("#tabButtonDashboard").removeClass("active");
    $("#menuButtonDashboard").removeClass("active");

    //Testsequence page
    $("#tabButtonTestSequences").addClass("active");
    $("#menuButtonTestSequences").addClass("active");
    let url = getProjectTabURL().toString().replace("dashboard", "testsequences");
    url = url + "/" + event.target.id.toString();
    ajaxRequestFragment(event, url.toString(), "", "GET");
}
