/*
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/>.
*/

/*---------------------------------------------------------------------------------------------------------------------|


__  __  ____  _____          _
|  \/  |/ __ \|  __ \   /\   | |
| \  / | |  | | |  | | /  \  | |
| |\/| | |  | | |  | |/ /\ \ | |
| |  | | |__| | |__| / ____ \| |____
|_|  |_|\____/|_____/_/    \_\______|



---------------------------------------------------------------------------------------------------------------------|*/

// Modal mode controls how created/deleted labels are manipulated in current main template
// 0 : list view (sequence or case)
// 1 : show or create view (sequence or case)
var modalMode = 0;

// Controls what unsaved changes modal is to be changed after saving/failing a save.
// 0 : none
// 1 : unsavedChangesClosing
// 2 : unsavedChangedSwitching
var unsavedChangesModalCode = 0;

// DEFAULT COLOR DATA
var defaultLabelColor = "#007bff";
var defaultLabelTextColor = "#ffffff";

// SELECTED LABEL DATA
var requestedLabelId = -1;
var currentSelectedLabelId = -1;
var currentSelectedLabelName = '';
var currentSelectedLabelDescription = '';
var currentSelectedLabelColor = defaultLabelColor;
var currentSelectedLabelTextColor = defaultLabelTextColor;

var isSelectedLabelNew = true;



//--------------------------------------------------------------------------------------------------------------------|
// LISTENERS ---|
//--------------------------------------------------------------------------------------------------------------------|

// NAME ---------------------------------------------------------|

/**
 * Trims the name fields value, checks its validity and puts it into the preview
 */
$("#inputLabelName").change(function() {
    let inputLabelName = $("#inputLabelName");

    // Trim the name and reset the validity check
    inputLabelName.val(inputLabelName.val().trim().replace(/\s\s+/g, ' '));

    // Check if the new value is valid
    resetValidity();
    checkValidity();

    // If the name isn't empty change the previews name
    if(!inputLabelName.val() == ''){
        // Set the preview
        $("#labelPreview").text(inputLabelName.val());
    } else {
        $("#labelPreview").text('Preview');
    }
});

$( "#inputLabelName" ).on("invalid", function(event) {
    $("#inputLabelName")[0].setCustomValidity('Please use 1-{{$maxNameLength}} letters, numbers or .,:_() .');
});

// DESC ---------------------------------------------------------|

/**
 * Puts the desc fields value into the preview
 */
$( "#inputLabelDescription" ).change(function() {
    let labelDesc = $( "#inputLabelDescription" ).val();

    $('#labelPreview').attr("data-original-title", labelDesc);
});

// COLOR ---------------------------------------------------------|

// Do to race conditions and various other thigs, every listener having to do with color is in the colorpicker js

// SAVE ----------------------------------------------------------|

/**
 * Saves the current selcted label
 */
$('#buttonSaveLabel').on('click', function(){
    saveLabel();
});

// DELETE ----------------------------------------------------------|

/**
 * Deletes the label
 */
$('#buttonDeleteLabelConfirm').on('click', function(){
    $(".tooltip").hide();
    $('#deleteLabels').modal('hide');
    deleteLabel();
});

// CLOSE ---------------------------------------------------------|

/**
 * Checks if unsaved changes are present. If so open the modal in bottom mode.
 */
$('#closeButtonBottom').on('click', function () {
    if(isChanged()) {
        $('#unsavedChangesModal').modal('show');
    } else {
        $('#modal-manage-labels').modal('hide');
        setLabelPropertiesFromId('buttonNewLabel');
    }
});

/**
 * Checks if unsaved changes are present. If so open the modal in top mode.
 */
$('#closeButtonTop').on('click', function () {
    if(isChanged()) {
        $('#unsavedChangesModal').modal('show');
    } else {
        $('#modal-manage-labels').modal('hide');
        setLabelPropertiesFromId('buttonNewLabel');
    }
});

// UNSAVED CHANGES -----------------------------------------------|

/**
 * Applies the unsaved changes, aka save
 */
$('#buttonApplyChangesClosing').on('click', function(){
    unsavedChangesModalCode = 1;
    saveLabel();
});


/**
 * discards the unsaved changes and closes the modals
 */
$('#buttonDiscardChangesClosing').on('click', function(){
    setLabelPropertiesFromId('buttonNewLabel');
    $('#unsavedChangesModal').modal('hide');
    $('#modal-manage-labels').modal('hide');
});

// UNSAVED CHANGES SWITCHING -------------------------------------|

/**
 * Applies the unsaved changes, aka save
 */
$('#buttonApplyChangesSwitching').on('click', function(){
    unsavedChangesModalCode = 2;
    saveLabel();
});

/**
 * discards the unsaved changes and closes the modals
 */
$('#buttonDiscardChangesSwitching').on('click', function(){
    setLabelPropertiesFromId(requestedLabelId);
    $('#unsavedChangesModalSwitching').modal('hide');
});


// LIST BUTTONS --------------------------------------------------|
/**
 * Gets the labelId and checks for changes. If changes it shows the modal and saves the id for later, otherwise swap label
 * @param labelId
 */
function onModalLabelClick(labelId) {
    requestedLabelId = labelId;

    if(isChanged()){
        $('#unsavedChangesModalSwitching').modal('show');
    } else {
        setLabelPropertiesFromId(labelId)
    }
}

/**
 * Fills the input fields based on what label was clicked. If its a new label, the fields are emptied and a flag is set
 * @param labelId
 */
function setLabelPropertiesFromId(labelId) {
    resetValidity();

    // Set the new label flag and id.
    if(labelId == 'buttonNewLabel'){
        $("#buttonDeleteLabel").attr("disabled", true);
        isSelectedLabelNew = true;
        currentSelectedLabelId = -1;

        $('#currentLabelText').text('New Label');
        $('#buttonSaveLabel').text('Add');
        resetInputFields();
    } else {
        $("#buttonDeleteLabel").attr("disabled", false);
        isSelectedLabelNew = false;
        currentSelectedLabelId = labelId;

        $('#currentLabelText').text('Edit Label');
        $('#buttonSaveLabel').text('Save');

        // Get the selected data
        let selectedLabel = $('#modal-container-label-' + labelId);

        let selectedLabelName = selectedLabel.text();
        let selectedLabelDescription = selectedLabel.attr('data-original-title');

        let selectedLabelColor = convertToHex(selectedLabel.css('background-color'));
        let selectedLabelTextColor = convertToHex(selectedLabel.css('color'));

        //Write the data into the input fields
        $('#inputLabelName').val(selectedLabelName);
        $('#inputLabelDescription').val(selectedLabelDescription);


        $('#inputLabelColor').css({
            "background-color":selectedLabelColor,
            "color": selectedLabelTextColor,
        });


        $("#labelPreview").text(selectedLabelName);
        $('#labelPreview').attr("data-original-title", selectedLabelDescription);
        $('#labelPreview').css({
            "background-color":selectedLabelColor,
            "color": selectedLabelTextColor,
        });

        currentSelectedLabelName = selectedLabelName;
        currentSelectedLabelDescription = selectedLabelDescription;
        currentSelectedLabelColor = selectedLabelColor;
        currentSelectedLabelTextColor = selectedLabelTextColor;
    }
}

/**
 * Clears the input fields and insert the default values
 */
function resetInputFields() {

    // Reset the input fields
    $('#inputLabelName').val('');
    $('#inputLabelDescription').val('');
    $('#inputLabelColor').css({
        "background-color":defaultLabelColor,
        "color": defaultLabelTextColor,
    });

    // Reset the preview
    $("#labelPreview").text('Preview');
    $('#labelPreview').attr("data-original-title", '');
    $('#labelPreview').css({
        "background-color":defaultLabelColor,
        "color": defaultLabelTextColor,
    });

    // Reset the selected data
    currentSelectedLabelName = '';
    currentSelectedLabelDescription = '';
    currentSelectedLabelColor = defaultLabelColor;
    currentSelectedLabelTextColor = defaultLabelTextColor;
}

//--------------------------------------------------------------------------------------------------------------------|
// UI ---|
//--------------------------------------------------------------------------------------------------------------------|

/**
 * Displays the error modal with the selected message
 * @param message
 */
function displayErrorMessageModal(message) {
    $("#errorMessage").text(message);
    $("#errorMessageModal").modal("show");
}

/**
 * Closes all change modals
 */
function closeUnsavedChangesModals() {
    $('#unsavedChangesModal').modal('hide');
    $('#unsavedChangesModalSwitching').modal('hide');
}

/**
 * Shows or hides the list label text based on the number of labels
 */
function setListLabelText() {
    let currentLabels = document.getElementById('listLabelContainer').getElementsByTagName('span');

    if((currentLabels.length > 1)) {
        $('#labelContainerText').hide();
    } else {
        $('#labelContainerText').show();
    }
}
/**
 * Shows or hides the show label text based on the number of labels
 */
function setShowLabelText() {
    let currentLabels = document.getElementById('showLabelContainer').getElementsByTagName('span');

    if((currentLabels.length > 1)) {
        $('#showContainerText').hide();
    } else {
        $('#showContainerText').show();
    }
}
/**
 * Shows or hides the show label text based on the number of assignments
 */
function setShowLabelTextForAssignments() {
    if(testAssignedLabelIds.length == 0) {
        $('#showContainerText').show();
    } else {
        $('#showContainerText').hide();
    }
}

//--------------------------------------------------------------------------------------------------------------------|
// CREATE/UPDATE/DELETE ---|
//--------------------------------------------------------------------------------------------------------------------|

/**
 * If isSelectedIsNew is true, save a new label and insert new labels in the current background. Otherwise update, and
 * update labels in the current background
 * @returns {boolean}
 */
function saveLabel() {
    // Get the fields
    let inputLabelName = $('#inputLabelName');
    let inputDesc = $("#inputLabelDescription");
    let inputColor = $("#inputLabelColor");

    // Get the values
    let labelId = currentSelectedLabelId;
    let labelName = inputLabelName.val().trim().replace(/\s\s+/g, ' ');
    let labelDesc = inputDesc.val().trim();
    let labelColor = convertToHex(inputColor.css('background-color'));
    let labelTextColor = convertToHex(inputColor.css('color'));

    // VALIDITY CHECKS --------------------------------------------------------|
    // If nothing changed just jump out
    if (!isChanged()) {
        closeUnsavedChangesModals();
        return false
    }

    // If name is empty let user know
    if(labelName == '') {
        closeUnsavedChangesModals();
        displayErrorMessageModal("Please enter a name for the label");
        return false
    }

    // Check name validity
    if(!checkValidity()){
        closeUnsavedChangesModals();
        reportValidity();
        return false
    }

    // Check for name duplications
    let currentLabelButtons = $(".label-list-btn");

    for( let i = 1; i < currentLabelButtons.length; i++) {
        if($(currentLabelButtons[i]).text() == labelName && currentSelectedLabelName != labelName) {
            displayErrorMessageModal("Label name is already in use");
            return false
        }
    }

    // ------------------------------------------------------------------------|

    $.ajax({
        url: `${currentURL().takeFirstSegments(3)}/labels/new`,
        type: "POST",
        data: {
            labelId: labelId,
            labelName: labelName,
            labelDesc: labelDesc,
            labelColor: labelColor,
            labelTextColor: labelTextColor
        }
    }).done(response => {

        // ADD - UPDATE THE LABEL IN THE UI --------------------------------------------------------------------------|
        if(isSelectedLabelNew) {

            // If the selected label was new, the server will respond with the labels new Id
            addLabelToModalContainer(response, labelName, labelDesc, labelColor, labelTextColor);
            switch(modalMode) {
                case 0:
                    addLabelToListContainer(response, labelName, labelDesc, labelColor, labelTextColor);
                    setListLabelText();
                    break;
                case 1:
                    addLabelToShowContainer(response, labelName, labelDesc, labelColor, labelTextColor);
                    setShowLabelText();
                    break;
            }
        } else {

            // If its not a new label just update the old one
            updateLabelInModalContainer(labelId, labelName, labelDesc, labelColor, labelTextColor);
            switch(modalMode) {
                case 0:
                    updateLabelInListContainer(labelId, labelName, labelDesc, labelColor, labelTextColor);
                    break;
                case 1:
                    updateLabelInShowContainer(labelId, labelName, labelDesc, labelColor, labelTextColor);
                    break;
            }
        }
        //-------------------------------------------------------------------------------------------------------------|

        // Close any modals if needed
        switch(unsavedChangesModalCode) {
            case 0:
                break;
            case 1:
                //Close the unsaved changes modals and the main modal and reset the fields
                closeUnsavedChangesModals();
                $('#modal-manage-labels').modal('hide');
                setLabelPropertiesFromId('buttonNewLabel');
                break;
            case 2:
                // Just close the modals
                closeUnsavedChangesModals();
                setLabelPropertiesFromId(requestedLabelId);
                break;
        }

        if(isSelectedLabelNew) {
            $('#currentLabelText').text('Edit Label');
            $('#buttonSaveLabel').text('Save');
            isSelectedLabelNew = false;
            currentSelectedLabelId = response;
        }

        getAndSetCurrentLabelValues();

        unsavedChangesModalCode = 0;
    }).fail(response => {
        // Close any unsaved changes modals
        $('#unsavedChangesModal').modal('hide');

        unsavedChangesModalCode = 0;
    });
}

/**
 * Deletes a label from the modal and removes it from the current background
 */
function deleteLabel() {
    $.ajax({
        url: `${currentURL().takeFirstSegments(3)}/labels/delete`,
        type: "PUT",
        data: {
            labelId: currentSelectedLabelId,
        }
    }).done(response => {

        removeLabelFromModalContainer(currentSelectedLabelId);

        // Remove instances of the label based on the modal mode
        switch(modalMode) {
            case 0:
                removeLabelFromListContainer(currentSelectedLabelId);

                // Reset the filter
                if(currentFilterIdList.includes(currentSelectedLabelId.toString())){
                    let index = currentFilterIdList.indexOf(currentSelectedLabelId.toString());

                    currentFilterIdList.splice(index, 1);
                    filterBasedOnListMode();
                }

                setListLabelText();
                break;
            case 1:
                removeLabelFromShowContainer(currentSelectedLabelId);
                setShowLabelText();
                break;
        }

        setLabelPropertiesFromId('buttonNewLabel');
    }).fail(response => {

    });
}

/**
 * Fills anew label in the modal container
 * @param labelId
 * @param labelName
 * @param labelDesc
 * @param labelColor
 * @param labelTextColor
 */
function addLabelToModalContainer(labelId, labelName, labelDesc, labelColor, labelTextColor) {
    $('#modalLabelContainer').append(
        $("<button></button>")
            .attr("id", "modal-container-label-" + labelId)
            .attr("class", "btn label-list-btn")
            .attr("data-toggle", "tooltip")
            .attr("data-original-title", labelDesc)
            .attr("data-placement", "left")
            .attr("onclick", "onModalLabelClick('" + labelId + "')")
            .attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";")
            .text(labelName)
            .tooltip());
}

/**
 * Fills a new label into the list containers
 * @param response
 * @param labelName
 * @param labelDesc
 * @param labelColor
 * @param labelTextColor
 */
function addLabelToListContainer(response, labelName, labelDesc, labelColor, labelTextColor) {
    $('#listLabelContainer').append(
        $("<span></span>")
            .attr("id", "list-container-label-" + response)
            .attr("class", "badge badge-primary clickIcon list-container-label-" + response)
            .attr("data-toggle", "tooltip")
            .attr("data-original-title", labelDesc)
            .attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";")
            .attr('onclick', "onListLabelClick('"+ response +"')")
            .text(labelName)
            .tooltip()
    );


    // Filter button
    $('#labelFilterContainer').append(
        $("<span></span>")
            .attr("id", "list-header-label-" + response)
            .attr("class", "badge badge-primary filterBadge listHeaderBadge clickIcon list-container-label-" + response)
            .attr("data-toggle", "tooltip")
            .attr("data-original-title", labelDesc)
            .attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";")
            .attr('onclick', "onListLabelClick('"+ response +"')")
            .text(labelName)
            .tooltip().append(
            $("<strong></strong>").append(
                $("<span></span>")
                    .attr('class', 'filterBadgeClose clickIcon')
                    .attr('id', response)
                    .text(' ×')
            )
        ).hide()
    );
}

/**
 * Fills a new label into the show containers
 * @param response
 * @param labelName
 * @param labelDesc
 * @param labelColor
 * @param labelTextColor
 */
function addLabelToShowContainer(response, labelName, labelDesc, labelColor, labelTextColor) {

    // ASSIGN CONTAINER -----------------------------------------------------------------------------|
    $('#assignLabelContainer').append(
        $("<div></div>")
            .attr('id', 'assign-container-item-' + response)
            .attr('class','input-group mb-3')
            .attr('style', 'margin-top: 1rem;margin-bottom: 0rem;cursor: pointer;')
            .attr('onclick', 'onShowLabelClick(' + response + ')')
            .append(
                $("<form></form>")
                    .attr('class', 'form-inline')
                    .append(
                        $("<div></div>")
                            .attr('class', 'form-group')
                            .append(
                                $("<div></div>")
                                    .attr('class', 'input-group-prepend')
                                    .append(
                                        $("<i></i>")
                                            .attr('id', 'assign-container-icon-' + response)
                                            .attr('class', 'fa input-group-text')
                                            .attr('data-toggle', 'tooltip')
                                            .attr('data-original-title', 'Click to assign/unassign')
                                            .attr('style', 'padding: 0.9rem')
                                            .tooltip()
                                    )
                            )
                    )
            )
    );

    // JQuery bug requires us to call insertAfter on its own
    $('#assign-container-icon-' + response).after(
        $("<span></span>")
            .attr('class', 'badge badge-primary clickIcon')
            .attr('id', 'assign-container-label-' + response)
            .attr('data-toggle', 'tooltip')
            .attr('data-original-title', labelDesc)
            .attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";" + "line-height: 2;")
            .text(labelName)
            .tooltip()
    );
    // SHOW LIST --------------------------------------------------------------------------------------------|

    $('#showLabelContainer').append(
        $("<span></span>")
            .attr("id", "show-container-label-" + response)
            .attr("class", "badge badge-primary clickIcon")
            .attr("data-toggle", "tooltip")
            .attr("data-original-title", labelDesc)
            .attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";")
            .attr('onclick', "onListLabelClick('"+ response +"')")
            .text(labelName)
            .tooltip()
            .hide()
    );
}

/**
 * Updates a label in the modal container
 * @param labelId
 * @param labelName
 * @param labelDesc
 * @param labelColor
 * @param labelTextColor
 */
function updateLabelInModalContainer(labelId, labelName, labelDesc, labelColor, labelTextColor) {
    let listLabel = $('#modal-container-label-' + labelId);

    listLabel.text(labelName);
    listLabel.attr("data-original-title", labelDesc);
    listLabel.attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";")
}

/**
 * updates the labels in the list containers
 * @param labelId
 * @param labelName
 * @param labelDesc
 * @param labelColor
 * @param labelTextColor
 */
function updateLabelInListContainer(labelId, labelName, labelDesc, labelColor, labelTextColor) {

    // LIST CONTAINER LABEL
    let listContainerLabel = $('#list-container-label-' + labelId);
    listContainerLabel.text(labelName);
    listContainerLabel.attr("data-original-title", labelDesc);
    listContainerLabel.attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";");


    // LIST LIST LABELS
    let listListLabels = $('.list-list-label-' + labelId);
    for(let i = 0; i < listListLabels.length; i++) {
        let listListLabel = $(listListLabels[i]);

        listListLabel .text(labelName);
        listListLabel .attr("data-original-title", labelDesc);
        listListLabel .attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";" + "float: right;")
    }


    // LIST HEADER LABEL
    let listHeaderLabel = $('#list-header-label-' + labelId);
    let isHidden = listHeaderLabel.is(":hidden");
    listHeaderLabel.text(labelName + ' ×');
    listHeaderLabel.attr("data-original-title", labelDesc);
    listHeaderLabel.attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";");
    if(isHidden) {
        listHeaderLabel.hide();
    }
}

/**
 * Updates the labels in the show containers
 * @param labelId
 * @param labelName
 * @param labelDesc
 * @param labelColor
 * @param labelTextColor
 */
function updateLabelInShowContainer(labelId, labelName, labelDesc, labelColor, labelTextColor){
    let assignLabel = $('#assign-container-label-' + labelId);
    let showLabel = $('#show-container-label-' + labelId);

    assignLabel.text(labelName);
    assignLabel.attr("data-original-title", labelDesc);
    assignLabel.attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";" + "line-height: 2;");

    showLabel.text(labelName);
    showLabel.attr("data-original-title", labelDesc);
    showLabel.attr("style", "background-color:" + labelColor + ";" + "color:" + labelTextColor + ";");

    // Make sure the show label is hidden if not assigned
    if(testAssignedLabelIds.includes(labelId.toString())) {
        showLabel.show();
    } else {
        showLabel.hide();
    }
}

/**
 * Removes the label from the modal container
 * @param labelId
 */
function removeLabelFromModalContainer(labelId){
    let listLabel = $('#modal-container-label-' + labelId);
    listLabel.remove();
}

/**
 * Removes the label from the list containers
 * @param labelId
 */
function removeLabelFromListContainer(labelId){
    let listLabel = $('.list-container-label-' + labelId);
    listLabel.remove();
}

/**
 * Removes the label from the show containers
 * @param labelId
 */
function removeLabelFromShowContainer(labelId){
    let assignItem = $('#assign-container-item-' + labelId);
    let showLabel = $('#show-container-label-' + labelId);

    assignItem.remove();
    showLabel.remove();
}

//--------------------------------------------------------------------------------------------------------------------|
// UTILITY ---|
//--------------------------------------------------------------------------------------------------------------------|
/**
 * Grabs the current input field values and inserts them into the current variables
 */
function getAndSetCurrentLabelValues() {
    // Get the fields
    let inputLabelName = $('#inputLabelName');
    let inputDesc = $("#inputLabelDescription");
    let inputColor = $("#inputLabelColor");

    // Get the values
    let labelName = inputLabelName.val().trim().replace(/\s\s+/g, ' ');
    let labelDesc = inputDesc.val().trim();
    let labelColor = convertToHex(inputColor.css('background-color'));
    let labelTextColor = convertToHex(inputColor.css('color'));

    currentSelectedLabelName = labelName;
    currentSelectedLabelDescription = labelDesc;
    currentSelectedLabelColor = labelColor;
    currentSelectedLabelTextColor = labelTextColor;
}

/**
 * Convert a rgb(255,255,255) into hex
 */
function convertToHex(colorval) {
    var parts = colorval.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    delete(parts[0]);
    for (var i = 1; i <= 3; ++i) {
        parts[i] = parseInt(parts[i]).toString(16);
        if (parts[i].length == 1) parts[i] = '0' + parts[i];
    }

    return '#' + parts.join('');
}


/**
 * compares the input field values with the current field values. If they don't match, we have a change
 * @returns {boolean}
 */
function isChanged(){
    // Get the fields
    let inputLabelName = $('#inputLabelName');
    let inputDesc = $("#inputLabelDescription");
    let inputColor = $("#inputLabelColor");

    // Get the values
    let labelName = inputLabelName.val().trim().replace(/\s\s+/g, ' ');
    let labelDesc = inputDesc.val().trim();
    let labelColor = convertToHex(inputColor.css('background-color'));
    let labelTextColor = convertToHex(inputColor.css('color'));

    if(currentSelectedLabelName != labelName){
        return true;
    } else if (currentSelectedLabelDescription != labelDesc) {
        return true;
    } else if (currentSelectedLabelColor != labelColor){
        return true;
    } else if (currentSelectedLabelTextColor != labelTextColor) {
        return true;
    }

    return false;
}
// VALIDITY ----------------------------------------|
/**
 * Resets the names validity message
 */
function resetValidity() {
    let inputLabelName = $("#inputLabelName");
    inputLabelName[0].setCustomValidity('');
}

/**
 * Checks the names validity
 * @returns {boolean}
 */
function checkValidity() {
    let inputLabelName = $("#inputLabelName");
    return inputLabelName[0].checkValidity();
}

/**
 * Report the names validity
 */
function reportValidity() {
    let inputLabelName = $("#inputLabelName");
    inputLabelName[0].reportValidity();
}

/*---------------------------------------------------------------------------------------------------------------------|
    Show and create have identical HTML for the label editing/assigning. Only diff is we save create labels
    together with the case, in the show template we save them immediatly.

   _____ _    _  ______          __
  / ____| |  | |/ __ \ \        / /
 | (___ | |__| | |  | \ \  /\  / /
  \___ \|  __  | |  | |\ \/  \/ /
  ____) | |  | | |__| | \  /\  /
 |_____/|_|  |_|\____/   \/  \/

 And
   ____                         _
  / ___|  _ __    ___    __ _  | |_    ___
 | |     | '__|  / _ \  / _` | | __|  / _ \
 | |___  | |    |  __/ | (_| | | |_  |  __/
  \____| |_|     \___|  \__,_|  \__|  \___|

---------------------------------------------------------------------------------------------------------------------|*/

var testAssignedLabelIds;

// Show and create use the same js/container id's. This flag controls how saving/updating is finally handled
var isInCreateMode = false;

/**
 * Based on what show label was clicked, saved/deletes a test label assignment and displays/removes that assignment
 * @param labelId
 */
function onShowLabelClick(labelId) {
    let assignIcon = $('#assign-container-icon-'  + labelId);
    let labelIdAsString = labelId.toString();

    // Has the label been assigned to the test ?
    if (testAssignedLabelIds.includes(labelIdAsString)) {
        // Uncheck the assign icon
        assignIcon.attr("class", "fa input-group-text")
            .attr("style","padding:0.9rem");

        // Remove the id from the assigned id list
        let index = testAssignedLabelIds.indexOf(labelIdAsString);
        if(index > -1){
            testAssignedLabelIds.splice(index, 1);
        }

        // Make the unassigned label invisible
        let showLabel = $('#show-container-label-'  + labelId);
        showLabel.hide();

        if(!isInCreateMode) {
            deleteTestLabel(labelId);
        }

    } else {
        // Check the assign icon
        assignIcon.attr("class", "fa fa-check input-group-text")
            .attr("style","");

        // Add the id to the assigned id list
        testAssignedLabelIds.push(labelIdAsString);

        // Make the assigned label visible
        let showLabel = $('#show-container-label-'  + labelId);
        showLabel.show();

        if(!isInCreateMode) {
            saveTestLabel(labelId);
        }
    }

    setShowLabelTextForAssignments();
}

/**
 * Checkmarks all show labels that are assigned to the test
 */
function checkmarkAssignedLabels() {
    for(let i = 0; i < testAssignedLabelIds.length; i++){
        let assignIcon = $('#assign-container-icon-'  + testAssignedLabelIds[i]);

        assignIcon
            .attr("class", "fa fa-check input-group-text")
            .attr("style","")
    }
}

/**
 * Shows all show container labels that are assigned to the test
 */
function showAssignedLabels() {
    for(let i = 0; i < testAssignedLabelIds.length; i++){
        let showLabel = $('#show-container-label-'  + testAssignedLabelIds[i]);

        showLabel.show();
    }
}

/**
 * Removes a assignment from the test
 * @param labelId
 */
function deleteTestLabel(labelId) {
    $.ajax({
        url: `${currentURL().takeFirstSegments(5)}/labels/delete`,
        type: "PUT",
        data: {
            labelId: labelId,
        }
    }).done(response => {

    }).fail(response => {

    });
}

/**
 * Saves a assignment to a test
 * @param labelId
 */
function saveTestLabel(labelId) {
    $.ajax({
        url: `${currentURL().takeFirstSegments(5)}/labels/new`,
        type: "POST",
        data: {
            labelId: labelId,
        }
    }).done(response => {

    }).fail(response => {

    });
}

/*---------------------------------------------------------------------------------------------------------------------|


  _      _____  _____ _______
 | |    |_   _|/ ____|__   __|
 | |      | | | (___    | |
 | |      | |  \___ \   | |
 | |____ _| |_ ____) |  | |
 |______|_____|_____/   |_|



---------------------------------------------------------------------------------------------------------------------|*/

// List mode controls whether labels filter cases or sequences
// 0 : list (case)
// 1 : list (sequence)
var listMode = 0;

var currentFilterIdList = [ '-1' ];

/**
 * Filters the list based on what label id was clicked
 */
$(".filterBadge").on('click', function(event) {
    event.stopPropagation();

    let target = $( event.target );

    onListLabelClick(getNumberOutOfId(target.attr('id')));
});

/**
 * Removes a filter based on id
 */
$(".filterBadgeClose").on('click', function(event) {
    event.stopPropagation();

    let target = $( event.target );

    onListLabelClick(getNumberOutOfId(target.attr('id')));
});

/**
 * Filters the list based on what id was clicked
 * @param labelId
 */
function onListLabelClick(labelId) {
    let labelIdString = labelId.toString();

    // Remove the id from the filterList if its already inside it
    if (currentFilterIdList.includes(labelIdString)) {
        // Remove the id from the filter id list
        let index = currentFilterIdList.indexOf(labelIdString);
        if(index > -1){
            currentFilterIdList.splice(index, 1);
        }
    } else {
        currentFilterIdList.push(labelIdString);
    }

    filterBasedOnListMode();
}

/**
 * Filters based on cases or sequences since their list items have different class names
 */
function filterBasedOnListMode() {
    switch(listMode) {
        case 0:
            filterCases();
            break;
        case 1:
            filterSequences();
            break;
    }
}

/**
 * Filters all cases based on the current filter id list
 */
function filterCases() {
    // If the length is 1, only the element '-1' is in the filter id list. That means we aren't filtering so show eveything
    if(currentFilterIdList.length == 1) {
        for(let k = 0; k < $('.testCaseLine').length; k++) {
            $($('.testCaseLine')[k]).show();
        }

        // Show in the top of the list that all are being displayed
        $('#labelFilterContainerText').text("(All)");
    } else {
        let alreadySetToHide = [];

        for(let i = 0; i < currentFilterIdList.length; i++) {
            let currentFilterId = currentFilterIdList[i];

            // If id is -1 skip it
            if (currentFilterId == -1) {
                continue;
            }

            for(let k = 0; k < $('.testCaseLine').length; k++) {
                if(($($('.testCaseLine')[k]).find('.list-container-label-' + currentFilterId)).length != 1){
                    $($('.testCaseLine')[k]).hide();

                    alreadySetToHide.push($('.testCaseLine')[k])
                } else {
                    if(!alreadySetToHide.includes($('.testCaseLine')[k])){
                        $($('.testCaseLine')[k]).show();
                    }
                }
            }
        }
        // Show in the top of the list that its being filtered for labels
        $('#labelFilterContainerText').text("with labels");
    }

    // Display/Hide the list header badges
    for(let j = 0; j < $('.listHeaderBadge').length; j++) {
        if( !currentFilterIdList.includes(getNumberOutOfId($($('.listHeaderBadge')[j]).attr('id')).toString())){
            $($('.listHeaderBadge')[j]).hide();
        } else {
            $($('.listHeaderBadge')[j]).show();
        }
    }
}

/**
 * Filters all sequences based on the current fiilter id list
 */
function filterSequences() {
    // If the length is 1, only the element '-1' is in the filter id list. That means we aren't filtering so show eveything
    if(currentFilterIdList.length == 1) {
        for(let k = 0; k < $('.testSequenceLine').length; k++) {
            $($('.testSequenceLine')[k]).show();
        }

        // Show in the top of the list that all are being displayed
        $('#labelFilterContainerText').text("(All)");
    } else {
        let alreadySetToHide = [];

        for(let i = 0; i < currentFilterIdList.length; i++) {
            let currentFilterId = currentFilterIdList[i];

            // If id is -1 skip it
            if (currentFilterId == -1) {
                continue;
            }

            for(let k = 0; k < $('.testSequenceLine').length; k++) {
                if(($($('.testSequenceLine')[k]).find('.list-container-label-' + currentFilterId)).length != 1){
                    $($('.testSequenceLine')[k]).hide();

                    alreadySetToHide.push($('.testSequenceLine')[k])
                } else {
                    if(!alreadySetToHide.includes($('.testSequenceLine')[k])){
                        $($('.testSequenceLine')[k]).show();
                    }
                }
            }
        }
        // Show in the top of the list that its being filtered for labels
        $('#labelFilterContainerText').text("with labels");
    }

    // Display/Hide the list header badges
    for(let j = 0; j < $('.listHeaderBadge').length; j++) {
        if( !currentFilterIdList.includes(getNumberOutOfId($($('.listHeaderBadge')[j]).attr('id')).toString())){
            $($('.listHeaderBadge')[j]).hide();
        } else {
            $($('.listHeaderBadge')[j]).show();
        }
    }
}

/**
 * Reads the number out of an id
 * @param anStringId
 * @returns {number}
 */
function getNumberOutOfId(anStringId) {
    return anStringId.match(/\d+/g).map(Number)[0];
}

