(function () {
    global.dashModule
        .controller('shopCartCtrl', ['$scope', '$http', '$', '$translate', 'Upload', 'utilsService', 'shopCartService', shopCartCtrl])
        .directive('shopCart', [shopCartDirective]);

    function shopCartDirective() {
        return {
            restrict: 'E',
            templateUrl: 'shop/html/shopCartTemplate'
        };
    }

    function shopCartCtrl($scope, $http, $, $translate, Upload, utilsService, shopCartService) {
        let addressType = '';
        const countryNames = {};
        $scope.DOCUMENT_TYPES = {
            'TEMPLATE_QUESTINNAIRE': 1,
            'QUESTIONNAIRE': 2,
            'TEMPLATE_AGREEMENT': 6,
            'AGREEMENT': 7
        };
        $scope.startOrderDetails = startOrderDetails;
        $scope.cartPackages = [];
        $scope.countries = [];
        $scope.details = {};
        $scope.delivery = {};
        $scope.billing = {};
        $scope.countryNames = {};
        $scope.updateQuantity = updateQuantity;
        $scope.removeFromCart = removeFromCart;
        $scope.actionButton = 'NEXT';
        $scope.prevButton = '';
        $scope.isStepVisible = isStepVisible;
        $scope.hasPrevStep = hasPrevStep;
        $scope.goToNextStep = goToNextStep;
        $scope.showHideDialog = showHideDialog;
        $scope.isDialogVisible = false;
        $scope.placeOrder = placeOrder;
        $scope.changeCountryName = changeCountryName;
        $scope.isCartEmpty = isCartEmpty;
        $scope.sumPrice = shopCartService.sumPrice;
        $scope.isAvailable = isAvailable;
        $scope.getAvailabilityMessage = getAvailabilityMessage;
        $scope.termsAndConditionCheckbox = false;
        $scope.setTermsCheckboxValue = setTermsCheckboxValue;
        $scope.getAlertClass = getAlertClass;
        $scope.isActionBtnDisabled = isActionBtnDisabled;
        $scope.deliveryEqualsBilling = {
            checked: false
        };
        $scope.setBillingSameAsDeliveryAddress = setBillingSameAsDeliveryAddress;
        $scope.getOptionAvailabilityClass = getOptionAvailabilityClass;
        $scope.documents = {};
        $scope.selectionSteps = {
            'show-order-items': {
                current: 'show-order-items',
                next: 'upload-customer-questionaire',
                prev: '',
                isActionPromise: false,
                beforeAction: isCartValid,
                action: getInfo
            },
            'upload-customer-questionaire': {
                current: 'upload-customer-questionaire',
                next: 'upload-agreement',
                prev: 'show-order-items',
                isActionPromise: false,
                beforeAction: isQuestionaireUploaded,
                action: () => {
                    return true;
                }
            },
            'upload-agreement': {
                current: 'upload-agreement',
                next: 'show-customer-details',
                prev: 'upload-customer-questionaire',
                isActionPromise: false,
                beforeAction: isAgreementUploaded,
                action: () => {
                    return true;
                }
            },
            'show-customer-details': {
                current: 'show-customer-details',
                next: 'show-customer-billing',
                prev: 'upload-agreement',
                isActionPromise: false,
                beforeAction: () => {
                    return true;
                },
                action: () => {
                    return true;
                }
            },
            'show-customer-billing': {
                current: 'show-customer-billing',
                next: '',
                prev: 'show-customer-details',
                isActionPromise: false,
                beforeAction: () => {
                    return true;
                },
                action: showHideDialog
            },
        };
        $scope.step = $scope.selectionSteps['show-order-items'];
        $scope.uploadFile = uploadFile;
        $scope.isOrderPlaced = false;

        function startOrderDetails() {
            getShopCart();
            isActionBtnDisabled();
            utilsService.registerFunction('isActionBtnDisabled', isActionBtnDisabled);
        }

        function getOptionAvailabilityClass(isAvailable) {
            return isAvailable ? '' : 'not-available';
        }

        function isStepVisible(step) {
            return step === $scope.step.current;
        }

        function getShopCart() {
            $http({
                method: 'POST',
                url: 'shop/api/getShopCart'
            }).then(setShopCartPackages, utilsService.onHttpError);
        }

        function setShopCartPackages(response) {
            if (typeof response.data !== 'undefined') {
                $scope.cartPackages = response.data;
                $.each($scope.cartPackages, function (key, packageObject) {
                    $scope.commercialLead = packageObject.commercialLead;
                    packageObject.quantity = parseInt(packageObject.quantity);
                    packageObject.extraFixedPrice = calculateTotalPrice(packageObject, 'fixedPrice');
                    packageObject.extraRecurrentPrice = calculateTotalPrice(packageObject, 'recurrentPrice') + calculateTotalPrice(packageObject, 'servicesPrice');
                });
            }
        }

        function calculateTotalPrice(packageObject, priceKey) {
            let prices = packageObject.options.map((option) => {
                return option[priceKey];
            });
            prices = prices.concat(packageObject.additionalPackages.map((additionalPackage) => {
                return additionalPackage[priceKey];
            }));

            return shopCartService.sumPrice(prices, 1);
        }

        function updateQuantity(packageObject) {
            const params = $.param({
                idPackage: packageObject.idPackage,
                idCustomerInstance: packageObject.idCustomerInstance,
                idPrice: packageObject.idPrice,
                quantity: packageObject.quantity
            });

            $http({
                method: 'POST',
                url: 'shop/api/updateQuantity',
                data: params
            }).then(updateMessage, utilsService.onHttpError);
        }

        function removeFromCart(packageObject) {
            const params = $.param({
                idCart: packageObject.idCart
            });

            $http({
                method: 'POST',
                url: 'shop/api/removeFromCart',
                data: params
            }).then(updateMessage, utilsService.onHttpError);
        }

        function updateMessage(response) {
            if (typeof response.data.messages !== 'undefined') {
                response.data.messages.forEach((messageObj) => {
                    const key = messageObj.key ? $translate.instant('shop.messages.' + messageObj.key) : '';
                    let translatedMessage = $translate.instant('shop.messages.' + messageObj.message);
                    translatedMessage = key !== '' ? key + ': ' + translatedMessage : translatedMessage;

                    if (messageObj.message !== 'NO_CHANGE') {
                        utilsService.displayMessage(messageObj.code, translatedMessage);
                    }

                    if (messageObj.message === 'PACKAGE_REMOVED_FROM_CART') {
                        getShopCart();
                        shopCartService.updateShopCartCount();
                    }

                    if (messageObj.message === 'ORDER_PLACED') {
                        getShopCart();
                        shopCartService.updateShopCartCount();
                        $scope.isOrderPlaced = true;
                    }

                    if (messageObj.message === 'FILE_UPLOADED') {
                        getCartDocuments();
                    }
                });
            }
        }

        function hasPrevStep() {
            return $scope.prevButton !== '';
        }

        function showWarning(translateKey) {
            const translatedMessage = $translate.instant('shop.messages.' + translateKey);
            utilsService.displayMessage('warning', translatedMessage);
        }

        function goToNextStep(action, promiseFinished) {
            if ($scope.step.isActionPromise && !promiseFinished) {
                $scope.step.beforeAction();
            } else {
                const beforeActionSuccesfull = promiseFinished || $scope.step.beforeAction();

                if (!$scope.isBtnDisabled && action === 'next' && beforeActionSuccesfull) {
                    $scope.step.action();
                }

                if ($scope.step[action] !== '' && (beforeActionSuccesfull || action === 'prev')) {
                    const newClassForActive = action === 'next' ? 'done-step' : 'inactive-step';
                    const removeClassForNew = action === 'next' ? 'inactive-step' : 'done-step';
                    $('.' + $scope.step.current).removeClass('active-step');
                    $('.' + $scope.step.current).addClass(newClassForActive);
                    $('.' + $scope.step[action]).removeClass(removeClassForNew);
                    $('.' + $scope.step[action]).addClass('active-step');
                    $scope.step = $scope.selectionSteps[$scope.step[action]];
                    if (action === 'next' && $scope.step.next === '') {
                        $scope.actionButton = 'SAVE';
                        isActionBtnDisabled();
                    } else {
                        isActionBtnDisabled(false);
                        $scope.actionButton = 'NEXT';
                    }
                    $scope.prevButton = (action === 'prev' && $scope.step.prev === '') ? '' : 'PREV';
                }
            }

        }

        function isCartValid() {
            let isCartValid = {
                qunatity: true,
                available: true
            };
            $scope.cartPackages.forEach((cartPackage) => {
                if (!cartPackage.quantity || cartPackage.quantity <= 0 || cartPackage.quantity > 100) {
                    isCartValid.qunatity = false;
                }

                if (!isAvailable(cartPackage)) {
                    isCartValid.available = false;
                }
            });

            if (!isCartValid.qunatity) {
                showWarning('INVALID_QUANTITY');
            }

            if (!isCartValid.available) {
                showWarning('PRODUCT_NOT_AVAILABLE');
            }

            return isCartValid.qunatity && isCartValid.available;
        }

        function getInfo() {
            if (isCartValid) {
                Promise.all([getCustomerDetails(), getCountries(), getCartDocuments()]).then(values => {
                    $scope.$evalAsync(() => {
                        setCustomerDetails(values[0]);
                        setCountries(values[1]);
                    });
                });
            }
        }

        function getCustomerDetails() {
            return $http({
                method: 'POST',
                url: 'shop/api/getCustomerDetails'
            });
        }

        function setCustomerDetails(response) {
            if (response.data) {
                $scope.delivery = response.data.delivery ? response.data.delivery : $scope.delivery;
                $scope.billing = response.data.billing ? response.data.billing : $scope.billing;
                $scope.vatCode = response.data.vat ? response.data.vat : '';
                $scope.countryNames = response.data.countryNames ? response.data.countryNames : $scope.countryNames;
            }
        }

        function getCountries() {
            return $http({
                method: 'POST',
                url: 'shop/api/getCountries'
            });
        }

        function setCountries(response) {
            $scope.countries = response.data || [];
        }

        function setBillingSameAsDeliveryAddress() {
            if (Object.keys($scope.delivery).length) {
                if ($scope.deliveryEqualsBilling.checked) {
                    $scope.billing.detailedAddress = $scope.delivery.detailedAddress;
                    $scope.billing.idCountrySelected = $scope.delivery.idCountrySelected;
                    changeCountryName('billing', $scope.billing.idCountrySelected);
                    $scope.billing.city = $scope.delivery.city;
                    $scope.billing.zipCode = $scope.delivery.zipCode;
                } else {
                    $scope.billing.detailedAddress = '';
                    $scope.billing.idCountrySelected = 0;
                    $scope.billing.city = '';
                    $scope.billing.zipCode = '';
                }
            }
        }

        function showHideDialog() {
            $scope.$evalAsync(() => {
                $scope.isDialogVisible = !$scope.isDialogVisible;
            });
        }

        function placeOrder() {
            $scope.isTermsChecked = shopCartService.getTermsCheckboxValue();
            if ($scope.isTermsChecked) {
                const params = $.param({
                    cartPackages: JSON.stringify($scope.cartPackages),
                    deliveryInfo: JSON.stringify($scope.delivery),
                    billingInfo: JSON.stringify($scope.billing),
                    details: JSON.stringify($scope.details)
                });

                $http({
                    method: 'POST',
                    url: 'shop/api/placeOrder',
                    data: params
                }).then(updateMessage, utilsService.onHttpError);
            } else {
                const errorMessage = $translate.instant('shop.messages.NOT_ACCEPTED_TERMS');
                utilsService.displayMessage('error', errorMessage);
            }
        }

        function changeCountryName(addrType, idCountry) {
            addressType = addrType;
            $http({
                method: 'POST',
                url: 'shop/api/getCountryDetailsById',
                data: $.param({
                    idCountry
                })
            }).then(setCountryName, utilsService.onHttpError);
        }

        function setCountryName(response) {
            if (response && response.data.length > 0) {
                countryNames[addressType] = response.data[0]['countryName'];
            }
            if ($scope.countryNames) {
                $scope.countryNames[addressType] = countryNames[addressType];
            } else {
                $scope.countryNames = countryNames;
            }
        }

        function isCartEmpty() {
            return $scope.cartPackages.length === 0;
        }

        function getCartDocuments() {
            let packagesIds = [];
            $scope.cartPackages.forEach((pkg) => {
                packagesIds.push(pkg.idPackage);
            });
            $http({
                method: 'POST',
                url: 'shop/api/getCartDocuments',
                data: $.param({
                    packages: JSON.stringify(packagesIds)
                })
            }).then(setDocuments, utilsService.onHttpError);
        }

        function setDocuments(response) {
            if (response.data) {
                $scope.documents[$scope.DOCUMENT_TYPES['TEMPLATE_QUESTINNAIRE']] = response.data[$scope.DOCUMENT_TYPES['TEMPLATE_QUESTINNAIRE']] ?
                    response.data[$scope.DOCUMENT_TYPES['TEMPLATE_QUESTINNAIRE']] : [];

                $scope.documents[$scope.DOCUMENT_TYPES['TEMPLATE_AGREEMENT']] = response.data[$scope.DOCUMENT_TYPES['TEMPLATE_AGREEMENT']] ?
                    response.data[$scope.DOCUMENT_TYPES['TEMPLATE_AGREEMENT']] : [];
            }
        }

        function isOrderDocumentUploaded(documentType) {
            let areAllDocumentsUploaded = true;
            $scope.documents[documentType].forEach((document) => {
                if (!document.isUploaded) {
                    areAllDocumentsUploaded = false;
                }
            });

            if (!areAllDocumentsUploaded) {
                showWarning('NOT_UPLOADED');
            }

            return areAllDocumentsUploaded;
        }

        function isQuestionaireUploaded() {
            return isOrderDocumentUploaded(1);
        }

        function isAgreementUploaded() {
            return isOrderDocumentUploaded(6);
        }

        function uploadFile(file, idPackage, documentType) {
            const idDocumentType = documentType === 'questionnaire' ? $scope.DOCUMENT_TYPES['QUESTIONNAIRE'] : $scope.DOCUMENT_TYPES['AGREEMENT'];
            if (file) {
                Upload.upload({
                    url: 'shop/api/uploadOrderDocument',
                    method: 'POST',
                    file: file,
                    data: {
                        idDocumentType,
                        idPackage
                    }
                }).then(updateMessage, utilsService.onHttpError);
            } else {
                let translatedMessage = $translate.instant('shop.messages.NO_FILE');
                utilsService.displayMessage('error', translatedMessage);
            }
        }

        function isAvailable(packageObj) {
            return packageObj.status === 'available' &&
                parseInt(packageObj.isLinkEnabled) === 1 &&
                packageObj.areOptionsAvailable &&
                packageObj.areAdditionalAvailable;
        }

        function getAvailabilityMessage(packageObj) {
            if (packageObj.status !== 'available') {
                return 'PACKAGE_UNAVIALABLE';
            }

            if (parseInt(packageObj.isLinkEnabled) !== 1) {
                return 'CL_UNAVIALABLE';
            }

            if (!packageObj.areOptionsAvailable) {
                return 'OPTIONS_UNAVAILABLE';
            }

            if (!packageObj.areAdditionalAvailable) {
                return 'ADDITIONAL_PACKAGES_UNAVAILABLE';
            }

            return '';
        }

        function setTermsCheckboxValue(termsAndConditionCheckbox) {
            shopCartService.setTermsCheckboxValues(termsAndConditionCheckbox);
        }

        function getAlertClass(termsAndConditionCheckbox) {
            return termsAndConditionCheckbox ? 'alert-success' : 'alert-warning';
        }

        function isActionBtnDisabled(isDisabled = true) {
            $scope.isBtnDisabled = $scope.actionButton === 'SAVE' ? isDisabled : false;
        }
    }
})();
