/*
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/util/common.js");
$.getScript("/static/js/util/ajax.js");

var xmlhttp = new XMLHttpRequest();
var url;
var protocolData;
var testCaseData;
var testSequenceData;
var dataComplete = 0;
var testCaseVersion;
var testSequenceVersion;
var testResultStatus = 0;
var selectedType;
var selectedProtocol;
var table = $("#protocolTable");
var selectCases = $("#inputSelectTestCase");
var selectSequences = $("#inputSelectTestSequence");
var selectedCase = selectCases.val();
var selectedSequence = selectSequences.val();


function typeSelection() {
    selectedType = $("input[name=protocolType]:checked").val();
    if(selectedType === "testsequences") {
        selectSequences.removeClass("d-none");
        selectCases.addClass("d-none");
        sequenceSelection();
    } else {
        selectCases.removeClass("d-none");
        selectSequences.addClass("d-none");
        caseSelection();
    }
}

function caseSelection() {
    selectedCase = selectCases.val();
    if(selectedCase === "none") {
        placeholderTable("Select a test case to display protocols.");
    } else {
        url = "../protocols/" + selectedType + "/" + selectedCase;
        getProtocolData(listDataReceive);
        var urlSeg = window.location.href.split("/");
        var updatedURL = "../../../" + urlSeg[3] + "/" + urlSeg[4] + "/" + urlSeg[5] + "/?type=" + selectedType + "&selected=" + selectedCase;
        history.pushState('data', '', updatedURL);
    }
}

function sequenceSelection() {
    selectedSequence = selectSequences.val();
    if(selectedSequence === "none") {
        placeholderTable("Select a test sequence to display protocols.");
    } else {
        url = "../protocols/" + selectedType + "/" + selectedSequence;
        getProtocolData(listDataReceive);
        var urlSeg = window.location.href.split("/");
        var updatedURL = "../../../" + urlSeg[3] + "/" + urlSeg[4] + "/" + urlSeg[5] + "/?type=" + selectedType + "&selected=" + selectedSequence;
        history.pushState('data', '', updatedURL);
    }
}

function getProtocolData(fkt) {
    xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", url, true);
    xmlhttp.send();

    xmlhttp.onreadystatechange = function() {
        if (this.readyState === 4 && this.status === 200) {
            fkt(this);
        }
    }
}

function listDataReceive(object) {
    if (object.responseText !== "") {
        protocolData = JSON.parse(object.responseText);
        fillTable();
    } else {
        if(selectedType === "testsequences") {
            placeholderTable("There are no test sequence protocols yet. Run some test sequences to get protocols.");
        } else {
            placeholderTable("There are no test case protocols yet. Run some test cases or sequences to get protocols.");
        }
    }
}

function placeholderTable(message) {
    table.empty();
    table.append($("<tr></tr>")
        .append($("<td></td>").attr("colspan", 4).text(message)));

}

function fillTable() {
    table.empty();
    for(var i = 0; i < protocolData.length; i++) {
        addRow(protocolData[i]);
    }
    updateFilter();
    jQuery("time.timeago").timeago();
}


function addRow(result) {
    var row = $("<tr></tr>");
    row.attr("id",result.TestVersion.TestVersion+"-"+result.ProtocolNr);
    row.attr("style","cursor: pointer;");
    if(selectedType === "testsequences") {
        row.attr("onClick",'showTestSequenceProtocol(event,"'+result.TestVersion.Project+'","'+ result.TestVersion.Test +'","'+ result.ProtocolNr +'")');
    } else {
        row.attr("onClick",'showTestCaseProtocol(event,"'+result.TestVersion.Project+'","'+ result.TestVersion.Test +'","'+ result.ProtocolNr +'")');
    }

    var resultCell = $("<td></td>");
    resultCell.append(generateResultIcon(result.Result));

    var variantCell = $("<td></td>");
    variantCell.text(result.SUTVariant);

    var versionCell = $("<td></td>");
    versionCell.text(result.SUTVersion);

    var executionDateCell = $("<td></td>");
    var executionDate = $("<time></time>");
    executionDate.addClass("timeago");
    executionDate.attr("datetime",result.ExecutionDate);
    var time = new Date(result.ExecutionDate).toLocaleString();
    executionDate.text(time);
    executionDateCell.append(executionDate);

    row.append(resultCell);
    row.append(variantCell);
    row.append(versionCell);
    row.append(executionDateCell);

    table.append(row);
}

/* loads the chosen test case protocol*/
// noinspection JSUnusedGlobalSymbols
function showTestCaseProtocol(event, project, testcase, protocolID) {
    var loadurl = urlify(window.location.pathname).
    takeFirstSegments(2).
    appendSegment(project).
    appendSegment("protocols").
    appendSegment("testcases").
    appendSegment(testcase).
    appendSegment(protocolID).
    toString();
    ajaxRequestFragment(event, loadurl, "", "GET");
}

/* loads the chosen test sequence protocol*/
// noinspection JSUnusedGlobalSymbols
function showTestSequenceProtocol(event, project, testsequence, protocolID) {
    var loadurl = urlify(window.location.pathname).
    takeFirstSegments(2).
    appendSegment(project).
    appendSegment("protocols").
    appendSegment("testsequences").
    appendSegment(testsequence).
    appendSegment(protocolID).
    toString();
    ajaxRequestFragment(event, loadurl, "", "GET");
}

function updateFilter() {
    var showPassed = document.getElementById("filterSuccessfulTest").checked;
    var showPassedWithComments = document.getElementById("filterPassWithCommentTest").checked;
    var showFailed = document.getElementById("filterFailedTest").checked;
    var showNotAssessed = document.getElementById("filterNotAssessedTest").checked;

    for(var i = 0; i < protocolData.length; i++) {
        var protocol = protocolData[i];
        var protocolFieldID = protocol.TestVersion.TestVersion+"-"+protocol.ProtocolNr;
        switch(protocol.Result) {
            case 1:
                //pass
                if(showPassed) {
                    filterVariantVersion(protocol);
                } else {
                    hideRow(protocolFieldID);
                    console.log("showPassed");
                }
                break;
            case 2:
                //passwithcomment
                if(showPassedWithComments) {
                    filterVariantVersion(protocol);
                } else {
                    hideRow(protocolFieldID);
                    console.log("showPassedWithComments");
                }
                break;
            case 3:
                //fail
                if(showFailed) {
                    filterVariantVersion(protocol);
                } else {
                    hideRow(protocolFieldID);
                    console.log("showFailed");
                }
                break;
            default:
                //Not Assessed
                if(showNotAssessed) {
                    filterVariantVersion(protocol);
                } else {
                    hideRow(protocolFieldID);
                    console.log("showNotAssessed");
                }
                break;
        }
    }
}

function filterVariantVersion (protocol) {
    var showVariant = $("#inputSelectTestVariant").val();
    var showVersion = $("#inputSelectTestVersion").val();

    if((showVariant !== "all" && protocol.SUTVariant !== showVariant) ||
        (showVersion !== "all" && protocol.SUTVersion !== showVersion)){
        hideRow(protocol.TestVersion.TestVersion+"-"+protocol.ProtocolNr);
        console.log("showVariantVersion");
    } else {
        showRow(protocol.TestVersion.TestVersion+"-"+protocol.ProtocolNr);
    }
}

function hideRow (protocolFieldID) {
    $("tr#"+protocolFieldID).addClass("d-none");
}
function showRow (protocolFieldID) {
    $("tr#"+protocolFieldID).removeClass("d-none");
}


function fillTestCaseResult() {
    var localUrl = window.location.pathname;
    var urlSeg = localUrl.split("/");
    url = "../../../protocols/" + urlSeg[4] + "/" + urlSeg[5];
    selectedProtocol = urlSeg[6] - 1;
    getProtocolData(singleDataReceive);
    url = "../../../testcases/" + urlSeg[5] + "/json";
    getProtocolData(testCaseDataReceive);
}

function singleDataReceive(object) {
    if (object.responseText !== "") {
        protocolData = JSON.parse(object.responseText);
        dataComplete = dataComplete + 1;
        checkIfDataReceiveComplete();
    } else {
        //Error receiving data from server
    }
}

function testCaseDataReceive(object) {
    if (object.responseText !== "") {
        testCaseData = JSON.parse(object.responseText);
        dataComplete = dataComplete + 2;
        checkIfDataReceiveComplete();
    } else {
        //Error receiving data from server
    }
}

function checkIfDataReceiveComplete() {
    if(dataComplete === 3 && protocolData.length > selectedProtocol) {
        console.log(protocolData);
        console.log(testCaseData);
        testCaseVersion = protocolData[selectedProtocol].TestVersion.TestVersion;
        console.log(testCaseVersion);
        fillTestCaseResultTemplate(protocolData[selectedProtocol], testCaseData);
    } else {
        //Bad Request (not existing protocol)
    }
}

function fillTestCaseResultTemplate(result, data) {
    $("#buttonBack")             .click(backToTestProtocolList);
    $("#protocolName").text("Protocol of " + result.TestVersion.Test);

    $("#contentTestCaseResult").append(generateResultIcon(result.Result));

    if(result.Comment !== "") {
        $("#contentTestCaseNotesContainer").removeClass("d-none");
        $("#contentTestCaseNotes").text(result.Comment);
    }

    var testCaseVersionData = data.TestCaseVersions[data.TestCaseVersions.length - testCaseVersion];
    console.log(testCaseVersionData);
    $("#contentTestCaseDescription").text(testCaseVersionData.Description);
    $("#contentTestCasePreconditions").text(testCaseVersionData.Preconditions);


    var stepList = $("#testStepsResultAccordion");

    for(i = 0; i < result.StepProtocols.length; i++ ) {
        var listElement = $("<li class=\"list-group-item\"></li>");
        var elementHeader = $("<a></a>");
        elementHeader.append(generateResultIcon(result.StepProtocols[i].Result)) ;
        if(testCaseVersionData.Steps[i] !== undefined) {
            elementHeader.append(" "+testCaseVersionData.Steps[i].Action);
        }
        var elementToogle = $("<a data-toggle=\"collapse\" aria-expanded=\"false\" " +
            "data-parent=\"#testStepsResultAccordion\" class=\"float-right\"></a>");
        elementToogle.attr("href","#testStepsResultAccordion"+i);
        elementToogle.attr("aria-controls","#testStepsResultAccordion"+i);
        elementToogle.append("<i class=\"fa fa-chevron-down d-print-none\" aria-hidden=\"true\"></i>");
        listElement.append(elementHeader);
        listElement.append(elementToogle);

        var elementBody = $("<div class=\"collapse\" role=\"tabpanel\">");
        elementBody.attr("id","testStepsResultAccordion"+i);

        var elementBodyTable = $("<table></table>");
        var expectedRow = $("<tr></tr>");
        expectedRow.append("<td>Expected: </td>");
        if(testCaseVersionData.Steps[i] !== undefined) {
            expectedRow.append("<td>" + testCaseVersionData.Steps[i].ExpectedResult +"</td>");
        }
        elementBodyTable.append(expectedRow);
        var observedRow = $("<tr></tr>");
        observedRow.append("<td>Observed: </td>");
        observedRow.append("<td>" +result.StepProtocols[i].ObservedBehavior+"</td>");
        elementBodyTable.append(observedRow);
        if(result.StepProtocols[i].Comment !== "") {
            var notesRow = $("<tr></tr>");
            notesRow.append("<td>Notes: </td>");
            notesRow.append("<td>" +result.StepProtocols[i].Comment+"</td>");
            elementBodyTable.append(notesRow);
        }
        elementBody.append(elementBodyTable);

        listElement.append(elementBody);
        stepList.append(listElement);
    }

    var executionDate = $("<time></time>");
    executionDate.addClass("timeago");
    executionDate.attr("datetime",result.ExecutionDate);
    var time = new Date(result.ExecutionDate).toLocaleString();
    executionDate.text(time);
    $("#contentTestCaseExecutionDate").append(executionDate);

    //$("#contentTestCaseTester").text("Description of " + result.user);
    $("#contentTestCaseSUTVariant").text(result.SUTVariant);
    $("#contentTestCaseSUTVersion").text(result.SUTVersion);
    var version = $("<a></a>");
    version.click(function(event) {
        ajaxRequestFragment(event, "../../../testcases/" + result.TestVersion.Test + "?version=" + result.TestVersion.TestVersion, "", "GET");
        updateTabs("testcases");
    });
    version.text(result.TestVersion.TestVersion);
    version.attr("href", "");
    $("#contentTestCaseVersion").html(version);
}


/* steps back to the test case list */
function backToTestProtocolList(event) {
    var requestURL = getProjectURL() + "/" + "protocols" + "/";
    ajaxRequestFragment(event, requestURL, "", "GET");
}
function generateResultIcon(resultState) {
    var icon = $("<i></i>");
    icon.attr("class","fa");
    icon.attr("aria-hidden","true");
    icon.attr("data-toggle","tooltip");
    icon.attr("data-placement","bottom");

    switch(resultState) {
        case 1:
            //pass
            icon.addClass("fa-check-circle text-success");
            icon.attr("title","Passed"); break;
        case 2:
            //passwithcomment
            icon.addClass("fa-info-circle text-warning");
            icon.attr("title","Passed with comments"); break;
        case 3:
            //fail
            icon.addClass("fa-times-circle text-danger");
            icon.attr("title","Failed"); break;
        default:
            //Not Assessed
            icon.addClass("fa-question-circle text-secondary");
            icon.attr("title","Not Assessed"); break;
    }
    return icon;
}

function fillTestSequenceResult() {
    var localUrl = window.location.pathname;
    var urlSeg = localUrl.split("/");
    url = "../../../protocols/" + urlSeg[4] + "/" + urlSeg[5];
    selectedProtocol = urlSeg[6] - 1;
    getProtocolData(testSequenceResultReceive);
    url = "../../../testsequences/" + urlSeg[5] + "/json";
    getProtocolData(testSequenceDataReceive);
}
function testSequenceResultReceive(object) {
    if (object.responseText !== "") {
        protocolData = JSON.parse(object.responseText);
        dataComplete = dataComplete + 1;
        checkIfSequenceDataReceiveComplete();
    } else {
        //Error receiving data from server
    }
}

function testSequenceDataReceive(object) {
    if (object.responseText !== "") {
        testSequenceData = JSON.parse(object.responseText);
        dataComplete = dataComplete + 2;
        checkIfSequenceDataReceiveComplete();
    } else {
        //Error receiving data from server
    }
}

function checkIfSequenceDataReceiveComplete() {
    if(dataComplete === 3 && protocolData.length > selectedProtocol) {
        console.log(protocolData);
        console.log(testSequenceData);
        testSequenceVersion = protocolData[selectedProtocol].TestVersion.TestVersion;
        console.log(testSequenceVersion);
        fillTestSequenceResultTemplate(protocolData[selectedProtocol], testSequenceData);
    } else {
        //Bad Request (not existing protocol)
    }
}

function fillTestSequenceResultTemplate(result, data) {
    $("#buttonBack")             .click(backToTestProtocolList);
    $("#protocolName").text("Protocol of " + data.Name);
    $("#contentTestSequenceDescription").text(data.SequenceVersions[data.SequenceVersions.length-result.TestVersion.TestVersion].Description);
    $("#contentTestSequencePreconditions").text(data.SequenceVersions[data.SequenceVersions.length-result.TestVersion.TestVersion].Preconditions);

    table.empty();
    for(var i = 0; i < result.CaseExecutionProtocols.length; i++) {
        url = "../../../protocols/testcases/" + result.CaseExecutionProtocols[i].Test;
        selectedProtocol = result.CaseExecutionProtocols[i].ProtocolNr;
        getProtocolData(testCaseDataInTestsequenceReceive);
    }

    $("#contentTestSequenceSUTVariant").text(result.SUTVariant);
    $("#contentTestSequenceSUTVersion").text(result.SUTVersion);

    var version = $("<a></a>");
    version.click(function(event) {
        ajaxRequestFragment(event, "../../../testsequences/" + result.TestVersion.Test + "?version=" + result.TestVersion.TestVersion, "", "GET");
        updateTabs("testsequences");
    });
    version.text(result.TestVersion.TestVersion);
    version.attr("href", "");
    $("#contentTestSequenceVersion").html(version);
}

function testCaseDataInTestsequenceReceive(object) {
    if (object.responseText !== "") {
        testCaseData = JSON.parse(object.responseText);
        addInTestSequenceRow(testCaseData[0]);
        switch(testCaseData[0].Result) {
            case 0: break;
            case 1: if(testResultStatus === 0) { testResultStatus = 1;} break;
            case 2: if(testResultStatus !== 3) { testResultStatus = 2;} break;
            case 3: testResultStatus = 3; break;
        }
        $("#contentTestSequenceResult").empty().append(generateResultIcon(testResultStatus));
        jQuery("time.timeago").timeago();
    } else {
        //Error receiving data from server
    }
}

function addInTestSequenceRow(result) {
    var row = $("<tr></tr>");
    row.attr("id",result.ProtocolNr);
    row.attr("style","cursor: pointer;");
    row.attr("onClick",'showTestCaseProtocol(event,"'+result.TestVersion.Project+'","'+ result.TestVersion.Test +'","'+ result.ProtocolNr +'")');

    var resultCell = $("<td></td>");

    resultCell.append(generateResultIcon(result.Result));

    var nameCell = $("<td></td>");
    url = "../../../testcases/" + result.TestVersion.Test + "/json/";
    getProtocolData(function(object) {
        if (object.responseText !== "") {
            var testCase = JSON.parse(object.responseText);
            console.log(testCase);
            nameCell.text(testCase.Name);
        } else {
            //Error receiving data from server
        }
    });
    var executionDate = $("<time></time>");
    executionDate.addClass("timeago");
    executionDate.attr("datetime",result.ExecutionDate);
    var time = new Date(result.ExecutionDate).toLocaleString();
    executionDate.text(time);
    $("#contentTestSequenceExecutionDate").empty().append(executionDate);

    //var timeCell = $("<td></td>");
    //var time = new Date(result.ExecutionDate).toLocaleString();
    //timeCell.text(time);

    row.append(resultCell);
    row.append(nameCell);
    //row.append(nameCell);

    table.append(row);
}