(function () {
    global.dashModule
        .directive('productsTemplateByCategoriesDragDrop', productsTemplateByCategoriesDragDropDirective);

    function productsTemplateByCategoriesDragDropDirective() {
        return {
            restrict: 'EA',
            scope: {
                actionType: '@'
            },
            controller: productsTemplateByCategoriesDragDropCtrl,
            templateUrl: 'packages/html/productsTemplateByCategoriesDragDropTemplate'
        };
    }

    function productsTemplateByCategoriesDragDropCtrl($scope, $, $http, $translate, utilsService, packagesUtilsService) {
        const categories = [];
        let elementDragged;
        let droppedInPackage = [];
        let droppedInProducts = [];
        let addingNewVirtualProduct;
        $scope.packagesByCategories = {};
        $scope.productUnit = {};
        $scope.productInfo = {};
        $scope.isProductSelected = isProductSelected;
        $scope.showQuantityField = showQuantityField;
        $scope.checkQuantityAmount = utilsService.verifyAmountAdded;

        $scope.getTitle = packagesUtilsService.getTitle;
        $scope.getVirtualProductsByCategories = getVirtualProductsByCategories;
        $scope.productDropped = productDropped;
        $scope.onDragStartFromProducts = onDragStartFromProducts;
        $scope.onDragStartFromPackage = onDragStartFromPackage;
        $scope.onDragStop = onDragStop;

        $scope.getButtonTitle = getButtonTitle;
        $scope.updatePackage = updatePackage;
        $scope.resetProducts = resetProducts;
        $scope.isResetBtnVisible = isResetBtnVisible;
        $scope.isAddVirtualProductsFormVisible = isAddVirtualProductsFormVisible;
        $scope.enableAddNewVirtualProducts = enableAddNewVirtualProducts;
        $scope.countrySelected = {};
        $scope.packageSelected = {};

        initProducts();

        function initProducts() {
            utilsService.registerFunction('getVirtualProductsByCategories', getVirtualProductsByCategories);
            getVirtualProductsByCategories(packagesUtilsService.getPackageTemplateSelected());
        }

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

        function getButtonTitle() {
            return $translate.instant('packages.buttons.' + $scope.actionType.toUpperCase() + '_TEMPLATE_PACKAGES');
        }

        function isProductSelected() {
            return !$.isEmptyObject($scope.productInfo);
        }

        function showQuantityField(category) {
            return category !== 'installation';
        }

        function isResetBtnVisible() {
            return $scope.actionType === 'edit';
        }

        function isAddVirtualProductsFormVisible() {
            return addingNewVirtualProduct;
        }

        function enableAddNewVirtualProducts() {
            addingNewVirtualProduct = !addingNewVirtualProduct;
        }

        function getVirtualProductsByCategories(packageTemplateSelected = {}) {
            if ($scope.actionType === 'create') {
                $scope.packageSelected = {};
            } else {
                if (packageTemplateSelected && Object.keys(packageTemplateSelected).length > 0) {
                    $scope.packageSelected = packageTemplateSelected || {};
                }
            }

            httpCall('packages/api/getVirtualProductsByCategories', setProductsByCategories);
        }

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

            Object.keys($scope.productsByCategories).forEach(category => {
                categories.push(category);
                $scope.packagesByCategories[category] = [];
            });

            if ($scope.packageSelected && $scope.packageSelected.id) {
                $scope.packageName = $scope.packageSelected.name || '';
                $scope.packageDescription = $scope.packageSelected.description || '';
                $scope.packageSelected.products.forEach(productInfo => {
                    $scope.packagesByCategories[productInfo.category].push(productInfo);
                    $scope.productUnit[productInfo.idProduct] = parseInt(productInfo.productUnit);
                });
            }
        }

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

            droppedInPackage = {
                key: productKey,
                value: product
            };
            droppedInProducts = {};
            elementDragged = 'product';
        }

        function onDragStartFromPackage(event, ui, product, productKey) {
            $('#' + $scope.actionType + '-packages-template-list-' + product.category).css({
                overflow: 'visible'
            });

            droppedInProducts = {
                key: productKey,
                value: product
            };
            droppedInPackage = {};
            elementDragged = 'package';
        }

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

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

        function productDropped(event, ui, placeToDrop, productCategory) {
            if (elementDragged !== placeToDrop) {
                if (!$scope.packagesByCategories[productCategory]) {
                    $scope.packagesByCategories[productCategory] = [];
                }
                if (placeToDrop === 'package') {
                    const productExists = $scope.packagesByCategories[productCategory].some(product => {
                        return product.idProduct === droppedInPackage.value.idProduct;
                    });
                    if(productExists) {
                        $scope.productUnit[droppedInPackage.value.idProduct]++;
                    } else {
                        $scope.packagesByCategories[productCategory].push(droppedInPackage.value);
                    }
                } else if (placeToDrop === 'product') {
                    $scope.packagesByCategories[productCategory].splice(droppedInProducts.key, 1);
                }
            }

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

        function updatePackage() {
            const productsInPackageList = [];
            let productsPerType;

            for (productsPerType in $scope.packagesByCategories) {
                $scope.packagesByCategories[productsPerType].forEach(product => {
                    product.productUnit = $scope.productUnit[product.idProduct] || 1;
                    productsInPackageList.push(product);
                });
            }

            const packageInfo = {
                packageName: $scope.packageName || '',
                packageDescription: $scope.packageDescription || '',
                idPackage: $scope.packageSelected && $scope.packageSelected.id ? $scope.packageSelected.id : 0,
                isForEdit: $scope.actionType === 'create' ? false : true
            };

            const params = {
                products: JSON.stringify(productsInPackageList),
                packageInfo: JSON.stringify(packageInfo)
            };

            if ($scope.actionType === 'create') {
                httpCall('packages/api/createTemplatePackagesData', showConfirmationMessage, params);
            } else if ($scope.actionType === 'edit') {
                httpCall('packages/api/updateInformationDataInPackageTemplate', showConfirmationMessage, params);
            }
        }

        function showConfirmationMessage(response) {
            if (response.data && typeof response.data.messageData !== 'undefined') {
                const translationDataMessages = {
                    country: $scope.countrySelected.name || '',
                    packageName: $scope.packageName,
                    packageReference: $scope.packageReference,
                    productsNumber: response.data.productsNumber || 0
                };

                if (response.data.messageData.message === 'PACKAGE_NAME_EXISTS') {
                    $('#packageName').focus();
                }

                response.data.messageData.forEach(messageObj => {
                    translationDataMessages.field = messageObj.field || '';
                    const message = $translate.instant('packages.forms.messages.' + messageObj.message, translationDataMessages);
                    utilsService.displayMessage(messageObj.code, message);

                    if (messageObj.code === 'success') {
                        if ($scope.actionType === 'create') {
                            $scope.packageName = '';
                            $scope.packageReference = '';
                            $scope.packageDescription = '';
                            Object.keys($scope.productUnit).map(idProduct => {
                                $scope.productUnit[idProduct] = 1;
                            });
                            getVirtualProductsByCategories();
                        } else if ($scope.actionType === 'edit') {
                            $scope.packageUpdated = response.data.packageUpdated;
                            packagesUtilsService.getPackageTemplates().then(setPackageAfterEdit, global.onHttpError);
                        }
                    } else {
                        if (response.data.messageData.type && response.data.messageData.limit) {
                            translationDataMessages.type = response.data.messageData.type;
                            translationDataMessages.limit = response.data.messageData.limit;
                        }
                    }
                });
            } else {
                const errorMessage = $translate.instant('packages.forms.messages.SERVER_ERROR');
                utilsService.displayMessage('error', errorMessage);
            }
        }

        function setPackageAfterEdit(response) {
            if (response.data) {
                utilsService.executeRegisteredFunction('setPackagesTemplates', response);
                $scope.packageSelected = {
                    id: $scope.packageUpdated.idPackage,
                    packageName: $scope.packageUpdated.packageName,
                    packageDescription: $scope.packageUpdated.packageDescription
                };
            }
        }

        function resetProducts() {
            getVirtualProductsByCategories();
            const message = $translate.instant('packages.forms.messages.RESET_PACKAGE');
            utilsService.displayMessage('success', message);
        }
    }
})();
