class ListManager {

    currentData = [];
    displayedData = [];
    editableTypes = [];
    type = '';

    referredTable = [];
    associationTable = [];

    constructor(listContainer, type, editableTypes) {
        this.listContainer = listContainer;
        this.editableTypes = editableTypes;
        this.type = type;

        if (type === 'article') {
            AjaxManager.getAll().then((data) => {
                this.currentData = data['articles'];
                this.referredTable = data['categories'];
                this.associationTable = data['article_categories'];
                this.generateList()
            });
        } else {
            AjaxManager.get(type).then((data) => {
                this.currentData = data;
                this.generateList()
            });
        }
    }

    generateList() {
        for (let i = 0; i < this.currentData.length; i++) {
            this.createNewListEntry(this.currentData[i]);
        }
    }

    createNewListEntry(item) {
        let listItem = this.getListItem(item);
        this.displayedData.push($(listItem));
        const index = this.displayedData.length - 1;
        let JQueryItem = this.displayedData[index];
        this.listContainer.append(JQueryItem);
        JQueryItem.on('click', () => {
            this.showEditPopup(index);
        });
    }

    deleteListEntry(id) {
        $('#listItem_' + id).remove();
    }

    getCategoriesOfArticle(articleId) {
        let filteredList = [];
        for (let i = 0; i < this.associationTable.length; i++) {
            if (this.associationTable[i]['article_id'] === articleId)
                filteredList.push(this.associationTable[i]['category_id']);
        }
        return filteredList;
    }

    getCategoryOfId(categoryId) {
        for (let i = 0; i < this.referredTable.length; i++) {
            if (this.referredTable[i]['id'] === categoryId) {
                return this.referredTable[i];
            }
        }
        return "";
    }

    getCategoryIcons(articleId) {
        let icons = "";
        let categories = this.getCategoriesOfArticle(articleId);
        for (let i = 0; i < categories.length; i++) {
            icons += "<i class='mdi mdi-" + this.getCategoryOfId(categories[i])["icon"] + "' style='margin-right: 5px'></i>";
        }
        return icons;
    }

    getListItem(item) {
        let listItem = "<li id='listItem_" + item["id"] + "'><div>";
        for (let i = 0; i < this.editableTypes.length; i++) {
            listItem += "<span class='list-" + this.editableTypes[i]["name"] + "'>";
            if (this.editableTypes[i]["type"] === "icon")
                listItem += "<i class='mdi mdi-" + item["icon"] + "' style='margin-right: 5px'></i></span>";
            else if (this.editableTypes[i]["type"] === 'checkboxes') {
                listItem += this.getCategoryIcons(item['id']);
            } else if (this.editableTypes[i]["type"] === 'image') {
                listItem += '<img src="../uploaded_images/' + item['id'] + '.jpg" /></span>'
            } else
                listItem += item[this.editableTypes[i]["name"]] + '</span>';
        }
        listItem += "</div></li>";
        return listItem;
    }

    getCategoryCheckboxes(articleId) {
        let checkboxes = "<div id='checkboxesContainer' style='display: flex'>";
        let categories = [];
        if (articleId !== undefined)
            categories = this.getCategoriesOfArticle(articleId);
        for (let i = 0; i < this.referredTable.length; i++) {
            let id = this.referredTable[i]['id'];
            let cat = this.getCategoryOfId(id);
            let checked = categories.indexOf(id) !== -1 ? 'checked' : '';
            checkboxes +=
                '<div class="custom-control custom-checkbox" style="margin-right: 20px">\n' +
                '<input type="checkbox" class="custom-control-input" id="checkbox_' + id + '"' + checked + ' >\n' +
                '<label class="custom-control-label" for="checkbox_' + id + '">' +
                '<i class="mdi mdi-' + cat["icon"] + '" style="margin-right: 5px"></i>' +
                '</label>\n' +
                '</div>';
        }
        checkboxes += '</div>';
        return checkboxes;
    }

    getFormData(defaultValues, index) {
        let formData = '<form id="popupForm" name="popupForm" method="post" enctype="multipart/form-data"><div class="form-group">';
        for (let i = 0; i < this.editableTypes.length; i++) {
            let inputId = this.editableTypes[i]['name'] + 'Input';
            let inputName = this.editableTypes[i]['name'];
            let inputType = this.editableTypes[i]['type'] === 'number' ? 'number' : 'text';
            let value = defaultValues[this.editableTypes[i]['name']] !== undefined ? defaultValues[this.editableTypes[i]['name']] : '';
            formData += '<label for="' + inputId + '">' + this.editableTypes[i]['description'] + ' :</label>';
            if (this.editableTypes[i]['type'] === 'image') {
                formData += this.getImagePicker(defaultValues['id'], index);
            } else if (this.editableTypes[i]['type'] === 'checkboxes') {
                formData += this.getCategoryCheckboxes(defaultValues['id']);
            } else {
                if (this.editableTypes[i]['name'] === 'icon')
                    formData += "<i class='mdi mdi-" + value + "' style='margin-left: 5px'></i>";
                formData += '<input name="' + inputName + '" id="' + inputId + '" type="' + inputType + '" placeholder="Entrez une valeur" class="form-control" value="' + value + '" required />';

            }
        }
        formData += "</div></form>";
        return formData;
    }

    getImagePicker(id, index) {
        let imageSrc = undefined;
        if (index !== -1)
            imageSrc = $(this.displayedData[index].find("img")[0]).attr('src');
        return (
            '<img style="width: 50px; height: 50px" src="' + imageSrc + '" id="image_' + id + '"/>' +
            '<div class="custom-file">\n' +
            '<input ' +
            'type="file" ' +
            'class="custom-file-input" ' +
            'id="fileInput"' +
            'accept="image/jpeg"' +
            'onchange="listManager.updatePickerImagePreview(this, \'image_' + id + '\')"' +
            '>\n' +
            '<label class="custom-file-label" for="customFile">Choose file</label>\n' +
            '</div>');
    }

    updatePickerImagePreview(picker, previewId) {
        $("#" + previewId).attr('src', window.URL.createObjectURL(picker.files[0]));
    }

    getFormValues(form) {
        let values = [];
        for (let i = 0; i < this.editableTypes.length; i++) {
            values.push(form.find('#' + this.editableTypes[i]['name'] + 'Input').val())
        }
        return values;
    }

    isFormValid(values) {
        let isValid = true;
        for (let i = 0; i < values.length; i++) {
            if (values[i] === '') {
                isValid = false;
                break;
            }
        }
        return isValid;
    }

    getCheckedCategories(content) {
        let checkedList = [];
        let checkboxes = content.find('#checkboxesContainer').children();
        for (let i = 0; i < checkboxes.length; i++) {
            let input = $(checkboxes[i]).find('input')[0];
            let id = $(input).attr('id').replace('checkbox_', '');
            if (input.checked)
                checkedList.push(id);
        }
        return checkedList;
    }

    insertFormDataIntoObject(values, object) {
        for (let i = 0; i < values.length; i++) {
            object[this.editableTypes[i]['name']] = values[i];
        }
        return object;
    }

    updateListItem(values, index) {
        for (let i = 0; i < values.length; i++) {
            if (this.editableTypes[i]['type'] === 'icon')
                this.displayedData[index].find(".mdi")[0].className = "mdi mdi-" + values[i];
            else
                this.displayedData[index].find(".list-" + this.editableTypes[i]['name']).text(values[i]);
        }
    }

    updateListItemCategories(categories, index) {
        if (index === -1)
            index = this.displayedData.length - 1;
        let iconContainer = this.displayedData[index].find(".list-category");
        for (let i = 0; i < categories.length; i++) {
            iconContainer.html(this.getCategoryIcons(this.currentData[index]['id']));
        }
    }

    updateAssociationList(articleId, newCategories) {
        let newTable = [];
        for (let i = 0; i < this.associationTable.length; i++) {
            if (this.associationTable[i]['article_id'] !== articleId)
                newTable.push(this.associationTable[i]);
        }
        for (let i = 0; i < newCategories.length; i++) {
            newTable.push({article_id: articleId, category_id: newCategories[i]});
        }
        console.log(newTable);
        this.associationTable = newTable;
    }

    updateArticleImage(image, index) {
        $(this.displayedData[index].find("img")[0]).attr('src', window.URL.createObjectURL(image));
    }

    showEditPopup(index) {
        let defaultValues = {};
        let title = "Créer une nouvelle entrée";
        if (index !== -1) {
            defaultValues = this.currentData[index];
            title = "Modifier l'entrée";
        }
        let formData = this.getFormData(defaultValues, index);
        let thisInstance = this;
        $.confirm({
            title: title,
            content: formData,
            buttons: {
                formSubmit: {
                    text: 'Sauvegarder',
                    btnClass: 'btn-blue',
                    action: async function () {
                        let image = undefined;
                        if (this.$content.find('input[type=file]').length > 0)
                            image = this.$content.find('input[type=file]')[0].files[0];

                        let values = thisInstance.getFormValues(this.$content);

                        if (!thisInstance.isFormValid(values)) {
                            $.alert('Merci de rentrer toutes les valeurs');
                            return false;
                        }
                        let itemToSave = {};
                        if (index !== -1) {
                            itemToSave = thisInstance.currentData[index];
                        }

                        itemToSave = thisInstance.insertFormDataIntoObject(values, itemToSave);

                        if (index !== -1) {
                            thisInstance.currentData[index] = itemToSave;
                            thisInstance.updateListItem(values, index);
                        }
                        let id = await AjaxManager.save(itemToSave, index === -1, thisInstance.type);
                        if (id >= 0 && index === -1) {
                            itemToSave["id"] = id;
                            thisInstance.currentData[thisInstance.displayedData.length] = itemToSave;
                            thisInstance.createNewListEntry(itemToSave);
                        } else if (id === -1) {
                            $.alert("Erreur serveur !");
                        }
                        if (id > 0 && thisInstance.type === 'article') {
                            let categories = thisInstance.getCheckedCategories(this.$content);
                            let data = {
                                id: id,
                                categories: categories
                            };
                            let result = await AjaxManager.save(data, true, 'article_categories');
                            if (result) {
                                thisInstance.updateAssociationList(id, categories);
                                thisInstance.updateListItemCategories(categories, index);
                                let imageResult = await AjaxManager.saveArticleImage(image, id);
                                if (imageResult === 0)
                                    thisInstance.updateArticleImage(image, index);
                            }
                        }
                    }
                },
                deleteButton: {
                    text: 'Supprimer',
                    btnClass: 'btn-red',
                    isHidden: index === -1,
                    action: function () {
                        thisInstance.showDeleteConfirmation(index);
                    }
                },
                cancelButton: {
                    text: 'Annuler',
                },
            }
        });
    }

    showDeleteConfirmation(index) {
        let thisInstance = this;
        $.confirm({
            title: "Confirmation",
            content: "Êtes vous sûr de vouloir supprimer cette entrée ?",
            buttons: {
                deleteButton: {
                    text: 'Confirmer',
                    btnClass: 'btn-red',
                    action: async function () {
                        let id = thisInstance.currentData[index]['id'];
                        let status = await AjaxManager.delete(id, thisInstance.type);
                        if (status === 0)
                            thisInstance.deleteListEntry(id);
                        else
                            $.alert("Erreur serveur !");
                    }
                },
                cancelButton: {
                    text: 'Annuler',
                },
            }
        });
    }

}
