(function () {
    global.dashModule
        .directive('createPackagesFromTemplate', createPackagesFromTemplateDirective)
        .controller('createPackagesFromTemplateController', ['$scope', '$http', '$', '$translate', '$timeout', 'utilsService', 'packagesUtilsService', createPackagesFromTemplateCtrl]);

    function createPackagesFromTemplateDirective() {
        return {
            restrict: 'E',
            templateUrl: 'packages/html/createPackagesFromTemplateTemplate'
        };
    }

    function createPackagesFromTemplateCtrl($scope, $http, $, $translate, $timeout, utilsService, packagesUtilsService) {
        const virtualCategoryNonExisting = [];
        const categories = [];
        const hasMultipleProducts = {};
        let droppedRealPackage;
        let realProductKeyReturned;
        let virtualProductKeyReturned;
        let elementDragged = '';
        $scope.isCountryAndPackageSelected = false;
        $scope.getTitle = packagesUtilsService.getTitle;
        $scope.productUnit = {};
        $scope.updateProducts = updateProducts;
        $scope.updateVirtualProducts = updateVirtualProducts;
        $scope.createPackageFromTemplate = createPackageFromTemplate;
        $scope.countrySelected = '';
        $scope.onDragStartFromProducts = onDragStartFromProducts;
        $scope.onDragStop = onDragStop;
        $scope.onDragStartFromPackage = onDragStartFromPackage;
        $scope.productDropped = productDropped;
        $scope.areTemplateAndCountrySelected = areTemplateAndCountrySelected;
        $scope.getCountryTranslationKey = getCountryTranslationKey;
        $scope.checkQuantityAmount = utilsService.verifyAmountAdded;
        $scope.initializeCreatePackages = initializeCreatePackages;
        $scope.packages = [];
        $scope.isCategoryInTemplate = isCategoryInTemplate;
        $scope.isAdditionalVirtualProductVisible = isAdditionalVirtualProductVisible;
        // default value for additional bussiness days for installation
        $scope.additionalInstallationDays = 5;
        $scope.selectedPackageTypeId = 1;
        $scope.getTemplateDescription = getTemplateDescription;
        $scope.tinymceOptions = utilsService.getTynimceOptions();
        $scope.uploadParams = {};

        function initializeCreatePackages() {
            const params = {getArray: true};
            httpCall('countries/api/getAllCountries', getCountries, params);
            httpCall('packages/api/getTemplatePackages', getTemplatePackages);
            getPackageTypes();
        }

        function getTemplateDescription() {
            const selectedTemplate = searchTemplateSelected() || {};
            return selectedTemplate.templateDescription || '';
        }

        function getTemplatePackages(response) {
            $scope.templates = response.data;
        }

        function getPackageTypes(){
            const params = {
                idPackage: $scope.packageSelected ? $scope.packageSelected.id : 0
            };
            httpCall('packages/api/getPackageTypes', setPackageTypes, params);
        }

        function setPackageTypes(response){
            if(response.data && response.data.packageTypes){
                $scope.packageTypes = response.data.packageTypes;
            }
        }

        function httpCall(httpUrl, successCallback, params) {
            const urlParams = params ? $.param(params) : {};
            $http({
                method: 'POST',
                url: httpUrl,
                data: urlParams
            }).then(successCallback, utilsService.onHttpError);
        }

        function areTemplateAndCountrySelected() {
            return typeof $scope.selectedCountryId !== 'undefined' && $scope.selectedCountryId !== 0 &&
                typeof $scope.idSelectedPackageTemplate !== 'undefined' && $scope.idSelectedPackageTemplate;
        }

        function getCountryTranslationKey() {
            return $scope.countrySelected === '' ? 'SELECT_COUNTRY' : 'SELECTED_COUNTRY';
        }

        function getProductsForPackages(response) {
            $scope.productsByCategories = typeof response.data !== 'undefined' ? response.data : [];
            getProductAndPackageCategories();
            setHeights();
        }

        function getCountries(response) {
            if (response.data) {
                $scope.countries = response.data;
            }
        }

        function onDragStartFromProducts(event, ui, product) {
            $('#products-list-' + product.category).css({
                overflow: 'visible'
            });
            $('.real-product-' + product.category).addClass('allowed-drop-zone');

            droppedRealPackage = product;
            realProductKeyReturned = '';
            virtualProductKeyReturned = '';
            elementDragged = 'product';
        }

        function onDragStartFromPackage(event, ui, virtualProductKey, realProductKey, category) {
            $('#packages-list-' + category).css({
                overflow: 'visible'
            });

            virtualProductKeyReturned = virtualProductKey;
            realProductKeyReturned = realProductKey;
            elementDragged = 'package';
        }

        function onDragStop(event, ui, product) {
            $('.package-list-' + product.category).css({
                'overflow-y': 'scroll'
            });
            $('.real-product-' + product.category).removeClass('allowed-drop-zone');

            $scope.productUnit[product.idProduct] = $scope.productUnit[product.idProduct] || 1;
        }

        function productDropped(event, ui, placeToDrop, productKey, productCategory) {
            const packageProduct = $scope.packagesByCategories[productCategory];

            if (placeToDrop === 'package') {
                if (elementDragged !== placeToDrop && packageProduct[productKey]) {
                    if (!packageProduct[productKey].real) {
                        packageProduct[productKey].real = [];
                    }

                    const productExists = packageProduct[productKey].real.some(product => {
                        return product.idProduct === droppedRealPackage.idProduct;
                    });
                    if(!productExists){
                        packageProduct[productKey].real.push(droppedRealPackage);
                    }

                }
            } else if (placeToDrop === 'product') {
                if (elementDragged !== placeToDrop) {
                    if ((virtualProductKeyReturned in packageProduct) &&
                        packageProduct[virtualProductKeyReturned].hasOwnProperty('real')) {

                        delete packageProduct[virtualProductKeyReturned].real;
                    } else if (packageProduct[realProductKeyReturned] &&
                        packageProduct[realProductKeyReturned].hasOwnProperty('real')) {

                        delete packageProduct[realProductKeyReturned].real;
                    }
                }
            }

            $(ui.helper).css({
                position: 'relative',
                left: 0,
                top: 0
            });
            elementDragged = '';
        }

        function getProductAndPackageCategories() {
            if ($scope.productsByCategories) {
                Object.keys($scope.productsByCategories).forEach((category, productKey) => {
                    virtualCategoryNonExisting[category] = $scope.packagesByCategories.hasOwnProperty(category);
                    categories.push(category);
                    if ($scope.productsByCategories[category][productKey]) {
                        hasMultipleProducts[category] = $scope.productsByCategories[category][productKey].hasMultiple;
                    }
                });
            }
        }

        function isCategoryInTemplate(category) {
            return virtualCategoryNonExisting[category];
        }

        function setHeights() {
            $timeout(function () {
                categories.forEach(category => {
                    const packagesHeight = $('#packages-list-' + category).height() + 3;

                    $('#products-list-' + category).css({
                        height: packagesHeight,
                        'overflow-y': 'overlay'
                    });

                    $('#pack-' + category + '-from-template-container').css({
                        height: packagesHeight
                    });
                });
            }, 10);
        }

        function isAdditionalVirtualProductVisible(category) {
            return hasMultipleProducts && hasMultipleProducts[category] ? parseInt(hasMultipleProducts[category]) : 0;
        }

        function updateProducts() {
            const idCountry = $scope.selectedCountryId;
            const params = {
                idCountry
            };
            const countryInfoSelected = $scope.countries.find(countryInfo => {
                return countryInfo.id === idCountry;
            });

            $scope.countrySelected = countryInfoSelected.name;
            $scope.translationData = {
                country: $scope.countrySelected
            };
            $scope.isString = false;
            let productsPerType;
            for (productsPerType in $scope.packagesByCategories) {
                $scope.packagesByCategories[productsPerType].forEach(packageDetails => {
                    if (packageDetails.hasOwnProperty('real')) {
                        delete packageDetails.real;
                    }
                });
            }
            utilsService.executeRegisteredFunction('saveCoverImage', $scope.uploadParams);

            httpCall('packages/api/getProductsByCategory', getProductsForPackages, params);
        }

        function updateVirtualProducts(afterCreate = false) {
            let virtualProducts = [];
            let productsByCategory;

            if (areTemplateAndCountrySelected()) {
                $.extend(virtualProducts, searchTemplateSelected().products);
                updateProducts();

                for (productsByCategory in virtualProducts) {
                    virtualProducts[productsByCategory].forEach(virtualProduct => {
                        $scope.productUnit[virtualProduct.idProduct] = parseInt(virtualProduct.quantity);
                        if (afterCreate) {
                            delete virtualProduct.real;
                        }
                    });
                }
                $scope.packagesByCategories = virtualProducts;
                setHeights();
            }

            $scope.uploadParams = {
                shouldShowBox: false,
                idCountry: $scope.selectedCountryId || 0,
                idPackage: $scope.idSelectedPackageTemplate || 0
            };
        }

        function createPackageFromTemplate() {
            const productsList = [];
            let packageHasRealProducts = true;
            let productsPerType;
            for (productsPerType in $scope.packagesByCategories) {
                if (!$scope.packagesByCategories[productsPerType].every(checkIfPackageHasRealProducts)) {
                    packageHasRealProducts = false;
                }
            }

            if (packageHasRealProducts) {
                let productsPerType;
                for (productsPerType in $scope.packagesByCategories) {
                    $scope.packagesByCategories[productsPerType].forEach(product => {
                        product.real.forEach(realProduct => {
                            realProduct.productUnit = $scope.productUnit[product.idProduct] ? $scope.productUnit[product.idProduct] : 1;
                            productsList.push(realProduct);
                        });
                    });
                }

                if (productsList) {
                    const packageInfo = {
                        packageName: $scope.packageName || '',
                        packageReference: $scope.packageReference || '',
                        packageDescription: $scope.packageDescription || '',
                        additionalInstallationDays: $scope.additionalInstallationDays || 0,
                        idCountry: $scope.selectedCountryId,
                        idPackageType: $scope.selectedPackageTypeId ? $scope.selectedPackageTypeId : 0,
                        idTemplate: $scope.idSelectedPackageTemplate
                    };

                    const params = {
                        packageData: JSON.stringify(productsList),
                        packageInfo: JSON.stringify(packageInfo),
                        shouldShowBox: false
                    };

                    httpCall('packages/api/createPackagesData', displayMessageConfirmation, params);
                } else {
                    utilsService.displayMessage('error', $translate.instant('packages.forms.messages.NO_PRODUCTS'));
                }
            } else {
                utilsService.displayMessage('error', $translate.instant('packages.forms.messages.NO_REAL_PRODUCTS'));
            }

            function checkIfPackageHasRealProducts(product) {
                return product.hasOwnProperty('real');
            }
        }

        function displayMessageConfirmation(response) {
            if (response.data.messageData) {
                const translationDataMessages = {
                    country: $scope.countrySelected,
                    packageName: $scope.packageName,
                    packageReference: $scope.packageReference,
                    productsNumber: response.data.productsNumber,
                    field: response.data.messageData.field || ''
                };
                response.data.messageData.forEach(messageObj => {
                    if (messageObj.code === 'success') {
                        $scope.packageName = '';
                        $scope.packageReference = '';
                        $scope.packageDescription = '';
                        updateVirtualProducts(true);
                    } else {
                        translationDataMessages.field = messageObj.field || '';
                        translationDataMessages.limit = messageObj.limit || '';
                    }

                    if (messageObj.message === 'PACKAGE_NAME_EXISTS') {
                        $('#package-name').focus();
                    }

                    const message = $translate.instant('packages.forms.messages.' + messageObj.message, translationDataMessages);
                    utilsService.displayMessage(messageObj.code, message);
                });
            } else {
                const errorMessage = $translate.instant('packages.forms.messages.SERVER_ERROR');
                utilsService.displayMessage('error', errorMessage);
            }
        }

        function searchTemplateSelected() {
            return $scope.templates.find(info => {
                return info.idTemplate === $scope.idSelectedPackageTemplate;
            });
        }
    }
})();
