(function() {
    global.dashModule.directive('productsByCategoriesDragDrop', productsByCategoriesDragDropDirective);

    function productsByCategoriesDragDropDirective() {
        return {
            restrict: 'EA',
            scope: {
                actionType: '@'
            },
            controller: productsByCategoriesDragDropCtrl,
            templateUrl: 'packages/html/productsByCategoriesDragDropTemplate'
        };
    }

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

        $scope.getTitle = packagesUtilsService.getTitle;
        $scope.getProductsByCategories = getProductsByCategories;
        $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.isAvailableClass = isAvailableClass;
        $scope.countrySelected = {};
        $scope.packageSelected = {};
        $scope.selectedPackageTypeId = 1;
        $scope.packageTypes = [];

        // default value for additional bussiness days for installation
        $scope.additionalInstallationDays = 5;
        $scope.packageHasInstallation = {
            create: true,
            edit: true
        };
        $scope.tinymceOptions = utilsService.getTynimceOptions();
        $scope.uploadParams = {};
        $scope.imageParams = {};

        initProductsPerCountry();

        function initProductsPerCountry() {
            utilsService.registerFunction('getProductsByCategories', getProductsByCategories);
            utilsService.registerFunction('getPackageTypes', getPackageTypes);
            getPackageTypes(packagesUtilsService.getCountryAndPackageSelected());
            getProductsByCategories(packagesUtilsService.getCountryAndPackageSelected());
        }

        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.forms.buttons.' + $scope.actionType.toUpperCase() + '_PACKAGE');
        }

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

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

        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 getProductsByCategories(data = {}) {
            if (Object.keys(data).length > 0) {
                $scope.countrySelected = data.countrySelected || {};
                $scope.packageSelected = data.packageSelected || {};
                $scope.selectedPackageTypeId = data.packageSelected && data.packageSelected.idPackageType || null;
            }
            $scope.translationData = {
                country: $scope.countrySelected.name || ''
            };
            $scope.isString = false;

            const params = {
                idCountry: $scope.countrySelected.id || 0,
                idPackage: $scope.packageSelected
                    ? $scope.packageSelected.id
                    : 0
            };
            $scope.uploadParams = params;
            $scope.imageParams = params;
            if($scope.actionType === 'create') {
                $scope.uploadParams.shouldShowBox = false;
            }
            httpCall('packages/api/getProductsByCategory', setProductsByCategories, params);
        }

        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) {
                const params = {
                    idCountry: $scope.selectedCountryId,
                    idPackage: $scope.packageSelected.id
                };
                httpCall('packages/api/getProductsInPackage', showProductsForPackages, params);
            }
        }

        function showProductsForPackages(response) {
            if (response.data.messageData) {
                const message = $translate.instant('packages.forms.messages.' + response.data.messageData.message);
                utilsService.displayMessage(response.data.messageData.code, message);
            } else {
                setProductsFromPackage(response.data);
            }
        }

        function setProductsFromPackage(packageProductsData) {
            $scope.packageName = $scope.packageSelected.name || '';
            $scope.packageReference = $scope.packageSelected.reference || '';
            $scope.packageDescription = $scope.packageSelected.description || '';
            $scope.additionalInstallationDays = parseInt($scope.packageSelected.additionalInstallationDays) || 0;
            $scope.packagesByCategories = packageProductsData;
            Object.keys($scope.packagesByCategories).forEach(category => {
                $scope.packagesByCategories[category].forEach(packageProduct => {
                    $scope.productUnit[packageProduct.idProduct] = parseInt(packageProduct.quantity);
                });
            });
            if ($scope.actionType === 'edit') {
                $scope.packageHasInstallation.edit = 'installation' in $scope.packagesByCategories && $scope.packagesByCategories.installation.length > 0
                    ? true
                    : false;
            }
        }

        function onDragStartFromProducts(event, ui, product, productKey) {
            $('#package-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) {
            $('#packages-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.productUnit[droppedInProducts.value.idProduct] = 1;
                    $scope.packagesByCategories[productCategory].splice(droppedInProducts.key, 1);
                }

                $scope.packageHasInstallation.edit = $scope.actionType === 'edit' && $scope.packagesByCategories.installation && $scope.packagesByCategories.installation.length > 0
                    ? true
                    : false;
            }

            $(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 || '',
                packageReference: $scope.packageReference || '',
                packageDescription: $scope.packageDescription || '',
                additionalInstallationDays: $scope.additionalInstallationDays || 0,
                idCountry: $scope.countrySelected.id || 0,
                idPackage: $scope.packageSelected && $scope.packageSelected.id
                    ? $scope.packageSelected.id
                    : 0,
                idPackageType: $scope.selectedPackageTypeId
                    ? $scope.selectedPackageTypeId
                    : 0,
                isForEdit: $scope.actionType === 'create'
                    ? false
                    : true
            };

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

            utilsService.executeRegisteredFunction('saveCoverImage', $scope.imageParams);

            if ($scope.actionType === 'create') {
                httpCall('packages/api/createPackagesData', showConfirmationMessage, params);
            } else if ($scope.actionType === 'edit') {
                httpCall('packages/api/updateInformationDataInPackage', 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;
                            });
                            getProductsByCategories();
                        } else if ($scope.actionType === 'edit') {
                            $scope.packageUpdated = response.data.packageUpdated;
                            packagesUtilsService.getPackagesPerCountry($scope.countrySelected.id).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('setPackages', response.data);
                $scope.packageSelected = {
                    id: $scope.packageUpdated.idPackage,
                    name: $scope.packageUpdated.packageName,
                    reference: $scope.packageUpdated.packageReference,
                    description: $scope.packageUpdated.packageDescription
                };
                packagesUtilsService.setCountryAndPackageSelected($scope.countrySelected.name, $scope.countrySelected.id, $scope.packageSelected);
            }
        }

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

        function isAvailableClass(isAvailable) {
            return typeof isAvailable !== 'undefined' && parseInt(isAvailable) === 0
                ? 'not-available-prdocut'
                : '';
        }
    }
})();
