/*
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/project/sut-versions-show.js");

// sutVersionData contains all versions and variants of the system under test
var sutVersionData = {};
// testCaseVersionData contains all the versions and variants of a test case.
// It is used to add versions which only exist in the test case but not in the sut anymore to the list of versions.
var testCaseVariantData;
// selectedVariants is an array of variant objects
var selectedVariants = {};

// Send a request to get the sut versions and variants of the project
var url = getProjectURL().appendSegment("versions").toString();
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
xmlhttp.send();
// Update the variants and versions
xmlhttp.onreadystatechange = function() {
    if (this.readyState === 4 && this.status === 200) {
        sutVersionData = JSON.parse(this.responseText);
        // Fill the drop down menu with the variants of the system under test
        fillVersions(sutVersionData, "#inputTestCaseSUTVersions");

        // Update which sut-variants and sut-versions are selected
        updateSelectedVersions();
        // Update the version list with the variants of the selected version
        updateVariantSelectionList(null);
    }
};

// Set Listeners for variants and versions
setVersionOnFocusListener();
setVariantsOnClickListener();

// Update versions and variants in dropdown and list when the
// modal with sut versions and variants is closed
$("#modal-manage-versions").on('hidden.bs.modal', function(e) {
    xmlhttp.open("GET", url, true);
    xmlhttp.send();
});

/* Save and update the versions and the versions on drop down selection change*/
function setVersionOnFocusListener() {
    var previousVersionKey;

    $("#inputTestCaseSUTVersions").on('focus', function () {
        // Store the current value on focus and on change
        previousVersionKey = $("#inputTestCaseSUTVersions").val();
    }).change(function() {
        updateVariantSelectionList(previousVersionKey);

        // Make sure the previous value is updated
        previousVersionKey = $("#inputTestCaseSUTVersions").val();
    });
}

/* Saves the currently selected variants */
function setVariantsOnClickListener() {
    $('#inputTestCaseSUTVariants').on('change', function () {
        saveSelectedVariants($("#inputTestCaseSUTVersions").val());
    });
}

// updateSelectedVersions updates the variable selectedVariants
// with the currently selected sut-versions and sut-variants
function updateSelectedVersions() {
    // Clear selected variants
    selectedVariants = {};
    // For each sut-version and sut variant, check if the test also
    // contains this variant/version. If the test contains
    // the variant/version, save it as selected.
    if (!sutVersionData) {
        return selectedVariants;
    }

    if (typeof isInCreateMode !== 'undefined' && isInCreateMode) {
        selectedVariants = sutVersionData;
        return;
    }
    $.each(sutVersionData, function(indexVar, sutVersion) {
        // Init the version
        selectedVariants[sutVersion.Name] = {Name:sutVersion.Name,Variants:{}};
        // Init the list of variants
        var variantList = [];
        $.each(sutVersionData[sutVersion.Name].Variants, function(indexVer, sutVariant) {
            // Return if case does not contain this sut-version
            if (!testCaseVariantData || !testCaseVariantData[sutVersion.Name] ||
                !sutVariant.Name in testCaseVariantData) {
                    return
            }
            // Check if the version in testCaseVariantData contains this sutVariant
            if (versionContainsVariant(testCaseVariantData[sutVersion.Name], sutVariant)) {
                variantList.push({Name:sutVariant.Name})
            }
        });
        selectedVariants[sutVersion.Name].Variants = variantList;
        // If a variant contains no versions...
        if (selectedVariants[sutVersion.Name].Variants.length === 0) {
            // Remove empty variants
            delete selectedVariants[sutVersion.Name];
        }
    });
    return selectedVariants;
}

function versionContainsVariant(version, variant) {
    var contains = false;
    $.each(version.Variants, function(indexCaseVar, caseSutVariant) {
        if (caseSutVariant.Name === variant.Name) {
            contains = true;
            return false
        }
    });
    return contains;
}

/* Updates the versions in the list based on the currently selected variant in the
 * drop down menu */
function updateVariantSelectionList(previousVersionKey) {
    // save selected versions of the previous selected variant
    if (previousVersionKey != null) {
        saveSelectedVariants(previousVersionKey);
    }

    // Get the newly selected variant and populate the versions list based on the new variant
    var selectedVersionKey = $('#inputTestCaseSUTVersions').val();
    populateVariantSelectionList(selectedVersionKey)
}

// saves the versions of the currently visible variant in the dropbox
// under the key "selectedVariantKey".
function saveSelectedVariants(selectedVersionKey) {
    var selectedVariantsList = [];
    $.each($('#inputTestCaseSUTVariants').val(), function(key, variantName) {
        selectedVariantsList.push({Name:variantName});
    });
    selectedVariants[selectedVersionKey] = {Name:selectedVersionKey,Variants:selectedVariantsList};
}

/* fill version list with the versions of the selected variant*/
function populateVariantSelectionList(selectedVersionKey) {
    var variantList = $('#inputTestCaseSUTVariants');

    // remove all previously shown elements
    variantList.empty();
    if (sutVersionData !== null && sutVersionData[selectedVersionKey] !== null) {
        // add versions of selected variant to list
        $.each(sutVersionData[selectedVersionKey].Variants, function(key, variant) {
            var listElement;
            if (selectedVariants[selectedVersionKey] != null && containsVariant(variant, selectedVariants[selectedVersionKey].Variants)) {
                listElement = ($("<option selected></option>")
                    .html('<span>' + variant.Name + '</span>'));
            } else {
                listElement = ($("<option></option>")
                    .html('<span>' + variant.Name + '</span>'));
            }
            variantList.append(listElement);
        });
    }
}

// containsVersion checks if a version with the same name already exists in an array of version objects.
// returns true if it exists and false it it does not exist
function containsVariant(variant, variantList) {
    var containsVariant = false;
    if (variantList !== null && variantList.length > 0) {
        variantList.forEach(function(vari) {
            if (vari.Name === variant.Name) {
                containsVariant = true;
            }
        });
    }
    return containsVariant;
}
