  /*global I18n, Util, $, _, tvOfferIncludes,Handlebars, Granite, add2BasketDatalayer,cartMini, genericFunctions, ajaxRequest, basketOperations, collectionsWarning,Toaster*/
  var Add2Basket = function () {
    var isCheckedCustomerDebits,
        customerHasDebs,
        CONST = {
              LAYOUT1: 1,
              LAYOUT2: 2,
              LAYOUT3: 3,
              CLICK_ADD_MOBILE_OFFER: "clickAddMobileOffer",
              CLICK_ADD_ACCESSORY_OFFER: "clickAddAccessoryOffer",
              CLICK_ADD_FIXED_OFFER: "clickAddFixedOffer",
              CLICK_ADD_SIM_OFFER: "clickAddSimOffer",
              CLICK_ADD_INSURANCE_OFFER: "clickAddInsuranceOffer",
              BUY_AS_GIFT_BASKET: 'BUY_AS_GIFT_BASKET',
              CUSTOMER_TYPE_R: "R",
              SUCCESS: "Success",
              BUSINESS: "Business",
              CUSTOMER_TYPE_B: "B",
              CUSTOMER_TYPE_R: "R",
              ERROR_ADDING_SIM_ONLY_PRODUCTS_TO_BASKET: "ERROR_ADDING_SIM_ONLY_PRODUCTS_TO_BASKET",
              ERROR_ADDING_STANDALONE_OFFER_TO_BASKET: "ERROR_ADDING_STANDALONE_OFFER_TO_BASKET",
              FIXED_OFFER_ALREADY_EXISTS : "FIXED_OFFER_ALREADY_EXISTS",
              STATUS_ACCESS_DOES_NOT_ALLOW_TO_PROCEED : "STATUS_ACCESS_DOES_NOT_ALLOW_TO_PROCEED",
              CREATED_CASE_UFE_NO_POSSIBLE_PROCEED_CHECKOUT : "CREATED_CASE_UFE_NO_POSSIBLE_PROCEED_CHECKOUT",
              BUNDLE_ALREADY_EXISTS: "BUNDLE_ALREADY_EXISTS",
	          TOP_UP_ALREADY_EXISTS: "TOP_UP_ALREADY_EXISTS",
	          BASKET_HAS_BILL_PAY_OFFER: "BASKET_HAS_BILL_PAY_OFFER",
              BASKET_HAS_FIXED_OFFER: "BASKET_HAS_FIXED_OFFER",
	          MAX_SUBSCRIPTIONS: "MAX_NUMBER_OF_SUBSCRIPTIONS_ACHIEVED",
              CONSUMER_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER: "CONSUMER_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER",
              BUSINESS_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER: "BUSINESS_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER",
              FULLVBU_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER: "vf_add2basket.EM_BC_19",
	          BASKET_HAS_PAYG_OFFER: "BASKET_HAS_PAYG_OFFER",
              BASKET_HAS_NO_SERVICEABILITY: "BASKET_HAS_NO_SERVICEABILITY",
              BILL_PAY_FLOW_PARAM: "?flowType=BILL_PAY",
              CONTEXT: "&context=ebu",
              UPGRADE_FLOW_PARAM: "?flowType=UPGRADE",
              SIM_TYPE: "TRIPGENSIM",
              ADDING_BASKET_BILLBAY: "/basket/items/mobile?flowType=BILL_PAY",
              ADDING_BASKET_SIM_Plans: "/basket/items/sim",
              PRODUCT_ID_EXCLUDES: ["mbb-offer-detail", "add2basket-fixedoffers-details-page"],
              ADDING_BASKET_BILLBAY_EBU: "/basket/items/mobile?flowType=BILL_PAY&context=ebu"
          },
          URL = {
              basketUrl: "/basket.html" + Util.getBasketContext(),
              basketUrlSwitch: "/basket.html?switch=true" + (Util.getBasketContext() === "" ? "" :'&'.concat(Util.getBasketContext().substr(1))),
              basketUrlMBB: "/basket.html?flowType=MBB" + (Util.getBasketContext() === "" ? "" :'&'.concat(Util.getBasketContext().substr(1)))
          },
          i18n = new I18n("vf_add2basket"),
          selectors = {
            simId: '#offerSimOnlyId'
        },
        stateObj = {
            productId: "",
            label: i18n.get("defaultLabel"),
            layout: CONST.LAYOUT1,
            templateId: "",
            html: "",
            device: {
                deviceProductId: "",
                productSpecId: "",
                tier: "",
                upgradeType: "",
                insurance: {
                    type: "",
                    coverageLevel: ""
                }
            },
            primaryPlan: {
                productId: "",
                priceId: "",
                addOnProductIds: ["", "", ""]
            },
            additionalPlans: [
                {
                productId: "",
                priceId: "",
                addOnProductIds: ["", "", ""]
            },
            {
                productId: "",
                priceId: "",
                addOnProductIds: ["", "", ""]
            }
        ],
            broadbandOffer: {
                productId: "",
                priceId: "",
                addOnProductIds: ["", "", ""]
            },
            landlineOffer: {
                productId: "",
                priceId: "",
                addOnProductIds: ["", "", ""]
            },
            tvOffer: {
                productId: "",
                priceId: "",
                addOnProductIds: ["", "", ""]
            },
            sim: {
                simType: ""
            },
            insurance: {
                type: "",
                coverageLevel: ""
            },
            addOns: [
                {
                id: "",
                instanceId: "",
                toAdd: "",
                toRemove: ""
            }
        ],
            campaign: {
                campaignId: "",
                origin: "",
                target: "",
                targetId: "",
                newSubscription: false
            },
            campaignBundle: {
                broadbandPlan: "",
                broadbandAddons: [],
                landlinePlan: "",
                landlineAddons: [],
                tvPlan: "",
                tvAddons: []
            },
            offerId: "",
            planId: "",
            customerId: "",
            bundleId: undefined,
            accessories: undefined,
            isUpgradeFlow: false,
            billingCustomersData: null,
            processContKey: null,
            selectedBasket: null,
            isFixedVoice: false,
            uan: null,
            isTopUpOffer: false,
            isPaygProduct: false,
            addOnProductIds: ["", "", ""],
            switchToVF: false,
            mbb: false
        },
        prefixTemplate = "#template_add2basket_layout",
        prefixApi = "/basket/items/",
        prefixId = "#add2basket-",
        controllerApi = {
            addAccessoryOffer: prefixApi + "accessory",
            addSmartwatchOffer: prefixApi + "smartwatches",
            addMobileOffer: prefixApi + "mobile",
            addFixedOffer: prefixApi + "fixed",
            addSimOffer: prefixApi + "sim",
            addTopUpOffer: prefixApi + "topup",
            editSimOffer: prefixApi + "editSim",
            editMobileOffer: prefixApi + "editMobile",
            editFixedOffer: prefixApi + "editFixedOffer",
            addInsuranceOffer: prefixApi + "insurance",
            installationAddress: "/serviceability/installationinfo/",
            changeMobileOffer: "/basket/offers/offer/mobile/change",
            changeBundleOffer: "/basket/offers/offer/bundle/change",
            addCampaign: "/basket/campaigns",
            addCampaignAndChangePlan: "/basket/campaigns/offer",
            billingCustomers: "/basket/billingCustomers",
            moveToBillPay: "/basket/offers/offer/payg/move",
            addSimTopUpOffer: prefixApi + "payg/sim",
            contactHasGiftBasket: "/basket/contactHasGiftBasket",
            changeSubscriptionDevice: prefixApi + "changeSubscriptionDevice",
            checkOperationCompatibilityCurrentBasket: "/basket/operationCompatibility",
            replaceStandaloneOffer: "/basket/replaceStandaloneOffer"
        },
        operations = {
            firstTimeConnectionPayG: "ftcPayG",
            firstTimeConnectionBillPay: "ftcBillPay",
            firstTimeConnectionFixed: "ftcFixed",
            firstTimeConnectionStandalone: "ftcStandalone",
            changePayGSubscriptionDevice: "changePayGSubscriptionDevice"
        },
        isMobileOffer = false,
        setStateObj = function (newStateObj) {
            stateObj = Object.assign(stateObj, newStateObj);
        },
        copyStateObj = function (keysToCopy) {
            if (!keysToCopy || !keysToCopy.length) return Object.assign({}, stateObj);

            return keysToCopy.reduce((copy, key) => {
                copy[key] = stateObj[key];
                return copy;
            }, {})
        },
        getMCCBODiscountId = function () {
            var billingOfferDiscount = JSON.parse(localStorage.getItem("campaignBbillingOffers"));
            if (billingOfferDiscount) {
                billingOfferDiscount = billingOfferDiscount.filter(function (bo) {
                    return bo.type === "Discount";
                });
                return billingOfferDiscount[0].productId;
            }
        },
        getProductId = function () {
            return stateObj.productId;
        },
        setProductId = function (productId) {
            stateObj.productId = productId;
        },
        getLabel = function () {
            return stateObj.label;
        },
        setLabel = function (label) {
            stateObj.label = label;
        },
        getLayout = function () {
            return stateObj.layout;
        },
        setLayout = function (layout) {
            stateObj.layout = layout;
        },
        getTemplateId = function () {
            return stateObj.templateId;
        },
        setTemplateId = function (templateId) {
            stateObj.templateId = templateId;
        },
        getHtml = function () {
            return stateObj.html;
        },
        setHtml = function (html) {
            stateObj.html = html;
        },
        getDevice = function () {
            return stateObj.device;
        },
        getOneNumberAccessories = function () {
            return stateObj.oneNumberAccessories;
        }
        setDevice = function (device) {
            stateObj.device = device;
        },
        setOneNumberAccessories = function (oneNumberAccessories) {
            stateObj.oneNumberAccessories = oneNumberAccessories;
        },
        setMBB = function (mbb) {
            stateObj.mbb = mbb;
        },
        getPrimaryPlan = function () {
            return stateObj.primaryPlan;
        },
        setPrimaryPlan = function (primaryPlan) {
            stateObj.primaryPlan = primaryPlan;
        },
        getAdditionalPlans = function () {
            return stateObj.additionalPlans;
        },
        setAdditionalPlans = function (additionalPlans) {
            stateObj.additionalPlans = additionalPlans;
        },
        getBroadbandOffer = function () {
            return stateObj.broadbandOffer;
        },
        setIsFixedVoice = function (isFixedVoice) {
            stateObj.isFixedVoice = isFixedVoice;
        },
        getFixedVoice = function () {
            return stateObj.isFixedVoice;
        },
        setUAN = function (uan) {
            stateObj.uan = uan;
        },
        getUAN = function () {
            return stateObj.uan;
        },
        getBasketURL = function () {
            return URL.basketUrl;
        },
        setBroadbandOffer = function (broadbandOffer) {
            stateObj.broadbandOffer = broadbandOffer;
        },
        getLandlineOffer = function () {
            return stateObj.landlineOffer;
        },
        setLandlineOffer = function (landlineOffer) {
            stateObj.landlineOffer = landlineOffer;
        },
        getTvOffer = function () {
            return stateObj.tvOffer;
        },
        setTvOffer = function (tvOffer) {
            stateObj.tvOffer = tvOffer;
        },
        getSim = function () {
            return stateObj.sim;
        },
        setSim = function (sim) {
            stateObj.sim = sim;
        },
        getOfferId = function () {
            return stateObj.offerId;
        },
        setOfferId = function (offerId) {
            stateObj.offerId = offerId;
        },
        getPlanId = function () {
            return stateObj.planId;
        },
        setPlanId = function (planId) {
            stateObj.planId = planId;
        },
        getBundleId = function () {
            return stateObj.bundleId;
        },
        setBundleId = function (bundleId) {
            stateObj.bundleId = bundleId;
        },
        getInsurance = function () {
            return stateObj.insurance;
        },
        setInsurance = function (insurance) {
            stateObj.insurance = insurance;
        },
        getAddOns = function () {
            return stateObj.addOns;
        },
        setAddOns = function (addOns) {
            stateObj.addOns = addOns;
        },
        getCampaign = function () {
            return stateObj.campaign;
        },
        setCampaign = function (campaign) {
            stateObj.campaign = campaign;
        },
        getCampaignBundle = function () {
            return stateObj.campaignBundle;
        },
        getCustomerId = function () {
            return stateObj.customerId;
        },
        setCustomerId = function (customerId) {
            stateObj.customerId = customerId;
        },
        getAccessories = function () {
            return stateObj.accessories;
        },
        setAccessories = function (accessories) {
            stateObj.accessories = accessories;
        },
        setUpgradeFlow = function (isUpgradeFlow) {
            stateObj.isUpgradeFlow = isUpgradeFlow;
        },
        getUpgradeFlow = function () {
            return stateObj.isUpgradeFlow;
        },
        setProcessContKey = function (data) {
            stateObj.processContKey = data;
        },
        getProcessContKey = function (data) {
            return stateObj.processContKey;
        },
        setBillingCustomersData = function (data) {
            stateObj.billingCustomersData = data;
        },
        getBillingCustomersData = function () {
            return stateObj.billingCustomersData;
        },
        setIsTopUpOffer = function (isTopUpOffer) {
            stateObj.isTopUpOffer = isTopUpOffer;
        },
        isTopUpOffer = function () {
            return stateObj.isTopUpOffer;
        },
        setIsPaygProduct = function (isPaygProduct) {
            stateObj.isPaygProduct = isPaygProduct;
        },
        chooseTemplate = function (layout) {
            switch (layout) {
                case CONST.LAYOUT1:
                case CONST.LAYOUT2:
                case CONST.LAYOUT3:
                    setTemplateId(prefixTemplate + layout);
                    return $(getTemplateId()).html();
                default:
                    setTemplateId(prefixTemplate + CONST.LAYOUT1);
                    return $(getTemplateId()).html();
            }
        },
        clearLocalStorage = function () {
            localStorage.removeItem("basket_summary_edit");
        },
        triggerEvent = function (event, triggerEvent) {
            add2BasketDatalayer.setAddCart();
            event.preventDefault();
            genericFunctions.closeErrorMessage();

            $(prefixId + getProductId()).trigger(triggerEvent);
        },
        clickAddAccessoryOffer = function (event) {
            triggerEvent(event, CONST.CLICK_ADD_ACCESSORY_OFFER);
        },
        clickAddAccessoryOfferMini = function (event) {
            triggerEvent(event, CONST.CLICK_ADD_ACCESSORY_OFFER);
        },
        clickAddMobileOffer = function (event) {
            triggerEvent(event, CONST.CLICK_ADD_MOBILE_OFFER);
        },
        clickAddFixedOffer = function (event) {
            triggerEvent(event, CONST.CLICK_ADD_FIXED_OFFER);
        },
        clickAddSimOffer = function (event) {
            triggerEvent(event, CONST.CLICK_ADD_SIM_OFFER);
        },
        clickAddInsuranceOffer = function (event) {
            triggerEvent(event, CONST.CLICK_ADD_INSURANCE_OFFER);
        },
        checkProductsEligible = function (
            requestPrefix,
            requestJson,
            add2basketSuccessCallback,
            add2basketErrorCallback
        ) {
            ajaxRequest.getSpinnerController().start();

            var completeCallback = function () {
                ajaxRequest.getSpinnerController().stop();
            };
            //FIXME REMOVE NEXT LINE WHEN PRODUCT ELIGIBILITY WORKS
            requestJson.basketIdentifier = basketOperations.getBasketCookie();

            requestJson.basketIdentifier.customerType = Util.getCustomerTypeFromGallery();
            if (
                Util.isUserLogged() &&
                (requestPrefix === CONST.ADDING_BASKET_BILLBAY ||
                    requestPrefix === CONST.ADDING_BASKET_SIM_Plans ||
                    requestPrefix === CONST.ADDING_BASKET_BILLBAY_EBU)
            ) {
                // get billing customer id in case of logged in user, BILLBAY CONSUMER (all plans include sim only plans)
                var successFn = function (customerId) {
                    requestJson.basketIdentifier.customerId = customerId;
                    ajaxRequest.postAlways(
                        requestPrefix,
                        requestJson,
                        add2basketSuccessCallback,
                        add2basketErrorCallback,
                        completeCallback,
                        60000
                    );
                };
                // get selected billing customer id
                window.omnichannelDataServices.account.getBillingCustomerId().then(successFn);
            } else {
                ajaxRequest.postAlways(
                    requestPrefix,
                    requestJson,
                    add2basketSuccessCallback,
                    add2basketErrorCallback,
                    completeCallback,
                    60000
                );
            }
        },
        checkCollections = function (
            requestPrefix,
            product,
            add2basketSuccessCallback,
            add2basketErrorCallback,
            isFixedOffer
        ) {
            var successCallback = function (response) {
                    if (response && response.collectionStatus && response.collectionStatus !== "NOT_IN_COLLECTION") {
                        collectionsWarning.showCollectionsWarningOverlay();
                    } else {
                        checkProductsEligible(
                            requestPrefix,
                            product,
                            add2basketSuccessCallback,
                            add2basketErrorCallback,
                            isFixedOffer
                        ); //check offers & products eligible
                    }
                },
                errorCallback = function () {
                    genericFunctions.refreshPortalMessage(i18n.get("errorGettingCollectionsStatus"), i18n.get("error"));
                };

            window.omnichannelDataServices.account.getAccountCollectionStatus().then(successCallback, errorCallback);
        },
        checkCollectionAndEligibility = function (
            requestPrefix,
            product,
            add2basketSuccessCallback,
            add2basketErrorCallback,
            isFixedOffer,
            ignoreOperationBasketCompatibility
        ) {
            var operationInProgress = ignoreOperationBasketCompatibility
                ? ""
                : extractOperationFromRequest(requestPrefix);
            var customerType = Util.getCustomerTypeFromGallery();

            checkIfCurrentOperationIsCompatibleWithCurrentBasket(operationInProgress, customerType, function () {
                if (Util.isUserLogged()) {
                    checkCollections(
                        requestPrefix,
                        product,
                        add2basketSuccessCallback,
                        add2basketErrorCallback,
                        isFixedOffer
                    );
                } else {
                    checkProductsEligible(
                        requestPrefix,
                        product,
                        add2basketSuccessCallback,
                        add2basketErrorCallback,
                        isFixedOffer
                    );
                }
            });
        },
        extractOperationFromRequest = function (requestUrl) {
            if (!requestUrl) {
                return "";
            }

            if (
                requestUrl.indexOf(controllerApi.addTopUpOffer) > -1 ||
                requestUrl.indexOf(controllerApi.addSimTopUpOffer) > -1
            ) {
                return operations.firstTimeConnectionPayG;
            }

            if (
                requestUrl.indexOf(controllerApi.addMobileOffer) > -1 ||
                requestUrl.indexOf(controllerApi.addSimOffer) > -1
            ) {
                return operations.firstTimeConnectionBillPay;
            }

            if (requestUrl.indexOf(controllerApi.addFixedOffer) > -1) {
                return operations.firstTimeConnectionFixed;
            }

            if (requestUrl.indexOf(controllerApi.changeSubscriptionDevice) > -1) {
                return operations.changePayGSubscriptionDevice;
            }

            if (requestUrl.indexOf(controllerApi.addAccessoryOffer) > -1) {
                return operations.firstTimeConnectionStandalone;
            }

            return "";
        },
        checkIfCurrentOperationIsCompatibleWithCurrentBasket = function (operationInProgress, customerType, callback) {
            if (!operationInProgress) {
                if (callback) {
                    callback();
                }
                return;
            }

            var dataObj = {
                question: Granite.I18n.get("vf_basketSummary.operationNotCompatibleWithCurrentBasket.question"),
                showOnClose: true,
                onClose: "angular.element('#basketProductsController').scope().hideClearToaster()",
                button: [
                    {
                        buttonClass: "button--primary",
                        identifier: "bpExistBasketYes",
                        label: i18n.get("vf_basketSummary.operationNotCompatibleWithCurrentBasket.continueButton")
                    },
                    {
                        buttonClass: "button--secondary",
                        identifier: "bpExistBasketNo",
                        label: i18n.get("vf_basketSummary.operationNotCompatibleWithCurrentBasket.cancelButton")
                    }
                ]
            };

            isCurrentBasketCompatibleWithOperation(
                operationInProgress,
                customerType,
                function (response, operationInProgress) {
                    var isCompatible = response.compatible;
                    if (isCompatible) {
                        if (callback) {
                            callback();
                        }
                        return;
                    }

                    var clearExistingBasketToaster = new Toaster();

                    var errorMessage;
                    if (
                        operationInProgress === operations.firstTimeConnectionFixed &&
                        response.errorCode === CONST.BASKET_HAS_FIXED_OFFER
                    ) {
                        basketOperations.clear(null, null, null);
                        genericFunctions.showPortalMessage(i18n.get("vf_add2basket.NO_SERVICEABILITY"));
                        return;
                    } else if (response.errorCode === CONST.BASKET_HAS_PAYG_OFFER) {
                        errorMessage = Granite.I18n.get("vf_add2basket.EM_BC_08");
                    } else if (response.errorCode === CONST.BASKET_HAS_BILL_PAY_OFFER) {
                        errorMessage = Granite.I18n.get("vf_add2basket.EM_BC_09");
                    } else if (response.errorCode === CONST.BASKET_HAS_FIXED_OFFER) {
                        errorMessage = Granite.I18n.get("vf_add2basket.EM_BC_09-fixed");
                    } else if (response.errorCode === CONST.BUSINESS_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER) {
                        errorMessage = Granite.I18n.get("vf_checkout.newCustomerMessage.ebu.soho.sme.EM_BC_16");
                    } else if (response.errorCode === CONST.CONSUMER_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER) {
                        errorMessage = Granite.I18n.get("vf_checkout.newCustomerMessage.ebu.soho.sme.EM_BC_15");
                    } else if (response.errorCode === CONST.BASKET_HAS_NO_SERVICEABILITY) {
                        genericFunctions.showPortalMessage(i18n.get("vf_add2basket.NO_SERVICEABILITY"));
                        return;
                    }

                    if (errorMessage) {
                        dataObj.question = errorMessage;
                    }

                    var callBackFns = [
                        {
                            fn: function () {
                                basketOperations.clear(null, callback, callback);
                            },
                            identifier: "bpExistBasketYes"
                        },
                        {
                            fn: function () {
                                clearExistingBasketToaster.hide();
                                ajaxRequest.getSpinnerController().stop();
                            },
                            identifier: "bpExistBasketNo"
                        }
                    ];

                    clearExistingBasketToaster.showGenericTemplate(dataObj, callBackFns);
                }
            );
        },
        add2basketSuccessCallback = function (response) {
            ajaxRequest.getSpinnerController().stop();
            if (response) {
                if (response.createDate) {
                    add2BasketDatalayer.setCreateCartDate(response.createDate);
                }
                if (response.editDate) {
                    add2BasketDatalayer.setUpdateCartDate(response.editDate);
                }
                basketOperations.setBasketIdentifier(response.processContKey);
                clearLocalStorage();
                cartMini.handleNewProductAddedToBasket(response.processContKey);

                if (response.warningMessages && response.warningMessages.length > 0) {
                    var warnCode = response.warningMessages[0];
                    if (warnCode === CONST.MAX_SUBSCRIPTIONS) {
                        genericFunctions.showPortalMessage(
                            i18n.get("vf_checkout.newCustomerMessage.ebu.soho.sme.WM_BC_19")
                        );
                        genericFunctions.onClosePortalMessage(function () {
                            window.location.href = URL.basketUrl;
                        });
                    }
                } else {
                    if (stateObj.mbb) {
                        window.location.href = URL.basketUrlMBB;
                    } else {
                        if (stateObj.switchToVF) {
                            window.location.href = URL.basketUrlSwitch;
                        } else {
                            window.location.href = URL.basketUrl;
                        }
                    }
                }
            }
        },
        add2basketEditModeSuccessCallback = function (response) {
            ajaxRequest.getSpinnerController().stop();
            if (response) {
                basketOperations.setBasketIdentifier(response.removeFromBasket.processContKey);
                clearLocalStorage();
                cartMini.handleNewProductAddedToBasket(response.removeFromBasket.processContKey);
                window.location.href = URL.basketUrl;
            }
        },
        buildConfigobjs = function (listOfProductsToRemove) {
            var msgLine1 = i18n.get("vf_add2basket.incompProductsAddLine1"),
                msgLine2 = i18n.get("vf_add2basket.incompProductsAddLine2"),
                products = listOfProductsToRemove.join(",");
            msgLine1 = msgLine1.replace("%product%", products);
            var dataObj = {
                showOnClose: "true",
                onClose: "toasterMessage.hide()",
                msgLine1: msgLine1,
                msgLine2: msgLine2
            };

            return dataObj;
        },
        handleIncompatiblesProductsAdded = function (data) {
            if (data.listProductsIncompatible) {
                var toasterMessage = new Toaster();
                var source = $("#messageIncompatibleProductsTemplate-template").html(),
                    template = Handlebars.compile(source);
                var htmlToaster = template(buildConfigobjs(data.listProductsIncompatible));
                toasterMessage.show(htmlToaster);
            }
        },
        add2basketErrorCallback = function (xhr) {
            var errorCode = xhr.getResponseHeader("errorCode");
            ajaxRequest.getSpinnerController().stop();

            if (xhr.status === 406) {
                handleIncompatiblesProductsAdded(xhr.responseJSON);
            }
            if (xhr.status === 403) { //errorCode === CONST.FULLVBU_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_19"));
            } else if (errorCode === CONST.ERROR_ADDING_SIM_ONLY_PRODUCTS_TO_BASKET) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_01"), i18n.get("error"));
            } else if (errorCode === CONST.ERROR_ADDING_STANDALONE_OFFER_TO_BASKET) {
                //TODO: Remove after QC13257-Provide and Change is delivered
                genericFunctions.refreshPortalMessage(
                    i18n.get("vf_accessory.errorAddingStandaloneToBasket"),
                    i18n.get("error")
                );
            } else if (errorCode === CONST.BUNDLE_ALREADY_EXISTS || errorCode === CONST.FIXED_OFFER_ALREADY_EXISTS) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_12"), i18n.get("error"));
            } else if (errorCode === CONST.STATUS_ACCESS_DOES_NOT_ALLOW_TO_PROCEED) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_serviceability.EM_36_12"), i18n.get("error"));
            } else if (errorCode === CONST.CREATED_CASE_UFE_NO_POSSIBLE_PROCEED_CHECKOUT) {
                genericFunctions.refreshPortalMessage(
                    i18n.get("vf_add2basket.CREATED_CASE_UFE_NO_POSSIBLE_PROCEED_CHECKOUT"),
                    i18n.get("error")
                );
            } else if (errorCode === CONST.TOP_UP_ALREADY_EXISTS) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_02"), i18n.get("error"));
            } else if (errorCode === CONST.BASKET_HAS_PAYG_OFFER) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_08"), i18n.get("error"));
            } else if (errorCode === CONST.BASKET_HAS_BILL_PAY_OFFER) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_09"), i18n.get("error"));
            } else if (errorCode === CONST.BASKET_HAS_FIXED_OFFER) {
                genericFunctions.refreshPortalMessage(i18n.get("vf_add2basket.EM_BC_09-fixed"), i18n.get("error"));
            } else if (errorCode === CONST.MAX_SUBSCRIPTIONS) {
                genericFunctions.refreshPortalMessage(
                    i18n.get("vf_checkout.newCustomerMessage.ebu.soho.sme.WM_BC_19"),
                    i18n.get("error")
                );
            } else if (errorCode === CONST.BUSINESS_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER) {
                genericFunctions.refreshPortalMessage(
                    i18n.get("vf_checkout.newCustomerMessage.ebu.soho.sme.EM_BC_16"),
                    i18n.get("error")
                );
            } else if (errorCode === CONST.CONSUMER_BASKET_HAS_INCOMPATIBLE_PRODUCTS_WITH_OFFER) {
                genericFunctions.refreshPortalMessage(
                    i18n.get("vf_checkout.newCustomerMessage.ebu.soho.sme.EM_BC_15"),
                    i18n.get("error")
                );
            } else {
                genericFunctions.refreshPortalMessage(i18n.get("errorAddItem"), i18n.get("error"));
            }
        },
        checkBasketForLoggedInUser = function () {
            var basketCookie = basketOperations.getBasketCookie(),
                data = getBillingCustomersData(),
                customerId,
                customerType,
                selected = false,
                processContKey = getProcessContKey(),
                authId;

            if (processContKey) {
                data.processContKey = processContKey;
            }

            if (!basketCookie.customerId) {
                for (var ind = 0; ind < data.billingCustomerModels.length; ind++) {
                    var billingCustomers = data.billingCustomerModels[ind];

                    if (billingCustomers.id && !billingCustomers.buyAsGift && !selected) {
                        customerId = billingCustomers.id;
                        customerType = getCustomerTypeFromAccounts(customerId);
                        billingCustomers.selected = true;
                        if (billingCustomers.authId) {
                            authId = billingCustomers.authId;
                        }
                        selected = true;
                    } else {
                        billingCustomers.selected = false;
                    }
                }

                if (
                    customerId &&
                    (!customerType || !basketCookie.customerType || customerType === basketCookie.customerType)
                ) {
                    basketCookie.customerId = customerId;
                    data.processContKey.customerId = customerId;
                    if (authId) {
                        basketCookie.authenticityIdentifier = authId;
                    } else {
                        basketCookie.authenticityIdentifier = "";
                    }

                    if (basketCookie.customerType === CONST.CUSTOMER_TYPE_R) {
                        basketCookie.customerType = "";
                    }

                    setBillingCustomersData(data);
                    basketOperations.setBasketIdentifier(basketCookie);
                }
            }
        },
        getCustomerTypeFromAccounts = function (customerId) {
            var customerType = null;
            if (
                customerId &&
                window.omnichannelControllerScope.accounts &&
                window.omnichannelControllerScope.accounts.list
            ) {
                var accountsList = window.omnichannelControllerScope.accounts.list;
                for (var i = 0; i < accountsList.length; i++) {
                    if (customerId === accountsList[i].billingCustomerId) {
                        customerType =
                            accountsList[i].customerTypeId === CONST.BUSINESS
                                ? CONST.CUSTOMER_TYPE_B
                                : CONST.CUSTOMER_TYPE_R;
                        break;
                    }
                }
            }
            return customerType;
        },
        addAccessoryOffer = function (isSmartwatch) {
            var product = {
                productId: getDevice().deviceProductId
            };

            var url = controllerApi.addAccessoryOffer;

            if (isSmartwatch) {
                url = controllerApi.addSmartwatchOffer;
                product.oneNumber = getPrimaryPlan().oneNumber;

                if (Util.isUserLogged()) {
                    var isOneNumberAddonSelected = _.get(product, "oneNumber.isOneNumberAddonSelected", false);

                    if (isOneNumberAddonSelected) {
                        var customerId = sessionStorage.getItem("selectedBC") || localStorage.getItem("customerId");
                        var basketIdentifier = basketOperations.getBasketCookie();
                        basketOperations.setBasketIdentifier({
                            ...basketIdentifier,
                            customerId
                        });
                    } else {
                        basketOperations.resetBasketIdentifierCustomer(basketOperations.getBasketCookie());
                    }

                }
            }

            checkCollectionAndEligibility(
                url,
                product,
                add2basketSuccessCallback,
                add2basketErrorCallback,
                false
            );
        },
        addAccessoryOfferMini = function () {
            var product = {
                productId: getProductId()
            };

            checkCollectionAndEligibility(
                controllerApi.addAccessoryOffer,
                product,
                add2basketSuccessCallback,
                add2basketErrorCallback,
                false
            );
        },
        addInsuranceOffer = function (insuranceSuccessCallback, insuranceErrorCallback) {
            var insurance = {
                offerId: getOfferId(),
                type: getInsurance().type,
                coverageLevel: getInsurance().coverageLevel
            };

            checkCollectionAndEligibility(
                controllerApi.addInsuranceOffer,
                insurance,
                add2basketSuccessCallback,
                insuranceErrorCallback,
                false
            );
        },
        moveToBillPay = function () {
            ajaxRequest.getSpinnerController().start();
            var offer = {
                device: getDevice(),
                addOns: getAddOns(),
                accessories: getAccessories()
            };

            checkCollectionAndEligibility(
                controllerApi.moveToBillPay,
                offer,
                add2basketSuccessCallback,
                add2basketErrorCallback,
                false
            );
        },
        isCurrentBasketCompatibleWithOperation = function (operation, customerType, callback) {
            var successCallback = function (response) {
                if (callback) {
                    callback(response, operation);
                }
            };
            var errorCallback = function () {
                if (callback) {
                    callback(true, operation);
                }
            };
            ajaxRequest.get(
                controllerApi.checkOperationCompatibilityCurrentBasket +
                    "?operation=" +
                    operation +
                    "&customerType=" +
                    customerType,
                successCallback,
                errorCallback,
                10000
            );
        },
        addMobileOffer = function (switchToVF, accessory) {
            ajaxRequest.getSpinnerController().start();
            if (switchToVF) {
                stateObj.switchToVF = true;
            }
            var isEdit = window.location.href.indexOf("mode=edit") !== -1,
                offer = {
                    offerId: getOfferId(),
                    bundleId: getBundleId(),
                    device: getDevice(),
                    primaryPlan: getPrimaryPlan(),
                    additionalPlans: getAdditionalPlans(),
                    accessories: accessory,
                    oneNumberAccessories: getOneNumberAccessories(),
                };

            if (stateObj.changeSubscriptionDevice) {
                var model = {
                    device: getDevice()
                };
                checkCollectionAndEligibility(
                    controllerApi.changeSubscriptionDevice,
                    model,
                    add2basketSuccessCallback,
                    add2basketErrorCallback,
                    false
                );
                return;
            }

            if (isEdit && !stateObj.buyAsGift) {
                var retrievedObject = JSON.parse(localStorage.getItem("basket_summary_edit"));
                if (retrievedObject !== null && retrievedObject !== undefined) {
                    var removeFromBasket = getRemoveObject(retrievedObject),
                        request = {
                            addMobileOfferToBasketRequest: {},
                            removeFromBasketRequest: {}
                        };
                    request.addMobileOfferToBasketRequest.offer = offer;
                    request.addMobileOfferToBasketRequest.basketIdentifier = basketOperations.getBasketCookie();
                    request.removeFromBasketRequest.id = removeFromBasket;
                    request.removeFromBasketRequest.basketIdentifier = basketOperations.getBasketCookie();
                    checkCollectionAndEligibility(
                        controllerApi.editMobileOffer,
                        request,
                        add2basketEditModeSuccessCallback,
                        add2basketErrorCallback,
                        false
                    );
                }
            } else {
                var url = Util.isPaygContext()
                    ? controllerApi.addTopUpOffer
                    : controllerApi.addMobileOffer +
                      CONST.BILL_PAY_FLOW_PARAM +
                      (Util.isEBUContext() ? CONST.CONTEXT : "");
                if (stateObj.buyAsGift) {
                    var callback = function (hasGiftBasket) {
                        ajaxRequest.getSpinnerController().stop();

                        if (hasGiftBasket) {
                            displayToasterAlreadyExistsGiftBasket(function () {
                                checkCollectionAndEligibility(
                                    url,
                                    offer,
                                    add2basketSuccessCallback,
                                    add2basketErrorCallback,
                                    false,
                                    true
                                );
                            });
                        } else {
                            checkCollectionAndEligibility(
                                url,
                                offer,
                                add2basketSuccessCallback,
                                add2basketErrorCallback,
                                false,
                                true
                            );
                        }
                    };

                    if (isEdit) {
                        callback(false);
                        return;
                    }

                    contactAlreadyHasGiftBasket(callback);
                } else {
                    checkCollectionAndEligibility(
                        url,
                        offer,
                        add2basketSuccessCallback,
                        add2basketErrorCallback,
                        false
                    );
                }
            }
        },
        displayToasterAlreadyExistsGiftBasket = function (proceedCallback) {
            var dataObj = {
                question: Granite.I18n.get("vf_buyAsGift.WM_CB_05"),
                showOnClose: true,
                onClose: "angular.element('#basketProductsController').scope().hideClearToaster()",
                button: [
                    {
                        buttonClass: "button--primary",
                        identifier: "bpExistBasketYes",
                        label: "Continue"
                    },
                    {
                        buttonClass: "button--secondary",
                        identifier: "bpExistBasketNo",
                        label: "Cancel"
                    }
                ]
            };

            var existBasketToaster = new Toaster();

            var callBackFns = [
                {
                    fn: proceedCallback,
                    identifier: "bpExistBasketYes"
                },
                {
                    fn: existBasketToaster.hide,
                    identifier: "bpExistBasketNo"
                }
            ];

            existBasketToaster.showGenericTemplate(dataObj, callBackFns);
        },
        contactAlreadyHasGiftBasket = function (callback) {
            ajaxRequest.get(controllerApi.contactHasGiftBasket, callback, callback);
        },
        addFixedOffer = function (isEditOffer) {
            var tvOffer = getTvOffer();
            tvOffer.tvBox = {
                numberOfBoxes: tvOfferIncludes.getNumberOfExtraBoxes(),
                tvBoxProductId: tvOfferIncludes.getZapperBoxId()
            };

            var offer = {
                bundleId: getBundleId(),
                broadbandOffer: getBroadbandOffer(),
                landlineOffer: getLandlineOffer(),
                tvOffer: tvOffer
            };

            if (isEditOffer) {
                var retrievedObject = JSON.parse(localStorage.getItem("basket_summary_edit")); //Os substituídos
                if (retrievedObject !== null && retrievedObject !== undefined) {
                    var removeFromBasket = getRemoveObject(retrievedObject),
                        request = {
                            addFixedOfferToBasketRequest: {},
                            removeFromBasketRequest: {}
                        };
                    request.addFixedOfferToBasketRequest.offer = offer;
                    request.addFixedOfferToBasketRequest.basketIdentifier = basketOperations.getBasketCookie();
                    request.removeFromBasketRequest.id = removeFromBasket;
                    request.removeFromBasketRequest.basketIdentifier = basketOperations.getBasketCookie();

                    checkCollectionAndEligibility(
                        controllerApi.editFixedOffer,
                        request,
                        add2basketSuccessCallback,
                        add2basketErrorCallback,
                        true
                    );
                }
            } else {
                checkCollectionAndEligibility(
                    controllerApi.addFixedOffer,
                    offer,
                    add2basketSuccessCallback,
                    add2basketErrorCallback,
                    true
                );
            }
        },
        addFixedOfferById = function (offerId) {
            checkCollectionAndEligibility(
                controllerApi.addFixedOffer + "/" + offerId,
                {},
                add2basketSuccessCallback,
                add2basketErrorCallback,
                true
            );
        },
        getRemoveObject = function (storageObject) {
            return {
                productId: storageObject.offId,
                instanceId: storageObject.offInsId,
                offerId: storageObject.offId,
                offerInstanceId: storageObject.offInsId
            };
        },
        addSimOffer = function (isEdit) {
            var offer = {
                offerId: getOfferId(),
                sim: getSim(),
                plan: getPrimaryPlan()
            };

            if (isEdit) {
                var retrievedObject = JSON.parse(localStorage.getItem("basket_summary_edit"));
                if (retrievedObject !== null && retrievedObject !== undefined) {
                    var removeFromBasket = getRemoveObject(retrievedObject);
                    var request = {
                        addSimOnlyToBasketRequest: {},
                        removeFromBasketRequest: {}
                    };
                    request.addSimOnlyToBasketRequest.offer = offer;
                    request.addSimOnlyToBasketRequest.basketIdentifier = basketOperations.getBasketCookie();
                    request.removeFromBasketRequest.id = removeFromBasket;
                    request.removeFromBasketRequest.basketIdentifier = basketOperations.getBasketCookie();

                    checkCollectionAndEligibility(
                        controllerApi.editSimOffer,
                        request,
                        add2basketSuccessCallback,
                        add2basketErrorCallback,
                        false
                    );
                }
            } else {
                var url = isTopUpOffer() ? controllerApi.addSimTopUpOffer : controllerApi.addSimOffer;
                checkCollectionAndEligibility(url, offer, add2basketSuccessCallback, add2basketErrorCallback, false);
            }
        },
        addSimOfferById = function (offerId) {
            var endPoint = controllerApi.addSimOffer,
                productId = offerId,
                isTopUp = $(selectors.simId).data("ftctopup");

            if (isTopUp) {
                offerId = "";
                endPoint = controllerApi.addSimTopUpOffer;
            }

            var offer = {
                offerId: "" + offerId,
                sim: { simType: CONST.SIM_TYPE },
                plan: { productId: "" + productId, addOnProductIds: [] }
            };

            checkCollectionAndEligibility(endPoint, offer, add2basketSuccessCallback, add2basketErrorCallback, true);
        },
        changeMobileOffer = function (changeOfferSuccessCallback, changeOfferErrorCallback) {
            var mobileOffer = {
                id: getOfferId()
            };

            ajaxRequest.post(
                controllerApi.changeMobileOffer,
                mobileOffer,
                changeOfferSuccessCallback,
                changeOfferErrorCallback,
                90000
            );
        },
        changeBundleOffer = function (changeOfferSuccessCallback, changeOfferErrorCallback) {
            var bundleOfferId = {
                id: getBundleId(),
                isFixedVoice: stateObj.isFixedVoice,
                isTv: "",
                isBroadband: ""
            };
            //TODO after service is properly working remove this
            //precisa de uma chamada aqui ao changebundle que ainda é preciso ser feito, ou outro serviço semelhante ao changeplan
            ajaxRequest.post(
                controllerApi.changeBundleOffer,
                bundleOfferId,
                changeOfferSuccessCallback,
                changeOfferErrorCallback,
                100000
            );
        },
        replaceStandaloneOffer = function(toBeRemovedProductSpecModel, standaloneReplacementOperationType) {
            ajaxRequest.getSpinnerController().start();

            if (!standaloneReplacementOperationType) standaloneReplacementOperationType = 'SMARTWATCH';

            var replacement = {
                toBeRemovedProductSpecModel: toBeRemovedProductSpecModel,
                toBeAddedProductSpecModel: { productId: getDevice().deviceProductId },
                standaloneReplacementOperationType: standaloneReplacementOperationType
            };

            ajaxRequest.post(
                controllerApi.replaceStandaloneOffer,
                replacement,
                add2basketSuccessCallback,
                add2basketErrorCallback,
                60000
            );
        },
        enableAdd2Basket = function (enable) {
            if (enable && !customerHasDebs) {
                $(prefixId + getProductId()).removeClass("button--disabled");
            } else {
                $(prefixId + getProductId()).addClass("button--disabled");
            }
        },
        changePlanAndAddCampaign = function () {
          ajaxRequest.getSpinnerController().start();

          var campaignItems = {
            campaign: getCampaign(),
            customerId: getCustomerId(),
            device: getDevice(),
            offer: {
              id: getOfferId(),
              planId: getPlanId(),
              discountIdMCCM: getMCCBODiscountId(),
            },
            isToAddCampaign: true,
            addOns: getAddOns(),
            bundle: getCampaignBundle(),
            discountIdMCCM: getMCCBODiscountId(),
            oneNumberAccessories: getOneNumberAccessories(),
            ...getPrimaryPlan(),
          };

          var successCallback = function () {
            var processCont = basketOperations.getBasketCookie();
            basketOperations.setBasketIdentifier(processCont);
            window.location.href = URL.basketUrl;
          };

          ajaxRequest.post(
            controllerApi.addCampaignAndChangePlan + CONST.UPGRADE_FLOW_PARAM,
            campaignItems,
            successCallback,
            add2basketErrorCallback,
            90000
          );
        },
        addCampaign = function () {
          ajaxRequest.getSpinnerController().start();

          var campaignItems = {
            campaign: getCampaign(),
            customerId: getCustomerId(),
            device: getDevice(),
            offer: {
              id: getOfferId(),
              planId: getPlanId(),
              discountIdMCCM: getMCCBODiscountId(),
            },
            addOns: getAddOns(),
            bundle: getCampaignBundle(),
            discountIdMCCM: getMCCBODiscountId(),
            oneNumberAccessories: getOneNumberAccessories(),
            ...getPrimaryPlan(),
          };

          var successCallback = function () {
            var processCont = basketOperations.getBasketCookie();
            basketOperations.setBasketIdentifier(processCont);
            window.location.href = URL.basketUrl;
          };

          ajaxRequest.post(
            controllerApi.addCampaign + CONST.UPGRADE_FLOW_PARAM,
            campaignItems,
            successCallback,
            add2basketErrorCallback,
            60000
          );
        },
        setButtonAddToBasketLabel = function (name) {
            var label = stateObj.defaultLabel;

            if (Util.isUserLogged()) {
                label = i18n.get("labelPrefix") + name + i18n.get("labelSufix");
            }

            $(prefixId + getProductId()).text(label);
        },
        slideToggleCustomerList = function () {
            $("#changeBasketList").slideToggle();
            $("#changeBasketIcon").toggleClass("accordion__chevron--up");
            blockBodyOverflowInMobile();
        },
        blockBodyOverflowInMobile = function () {
            if (Util.isScreenMobileSize()) {
                if ($("#changeBasketIcon").hasClass("accordion__chevron--up")) {
                    $("html, body").css("overflow", "hidden");
                } else {
                    $("html, body").css("overflow", "auto");
                }
            }
        },
        handleClickChangeBillingCustomer = function () {
            var billingCustomersData = getBillingCustomersData();
            var basketIdentifier = {
                    contactId: $(this).children().attr("data-contactId"),
                    customerId: $(this).children().attr("data-billingcustid"),
                    authenticityIdentifier: $(this).children().attr("data-authId")
                },
                name = $(this).children().text();
            $("#changeBasketList li a").removeClass("navigation__item--bold");
            $(this).children().addClass("navigation__item--bold");

            basketOperations.setBasketIdentifier(basketIdentifier);
            setButtonAddToBasketLabel(name);
            slideToggleCustomerList();

            // Update basket selected
            var filter = {};
            if (!basketIdentifier.customerId) {
                // filter to find the "new Customer" basket
                filter.newCustomer = true;
            } else {
                filter.id = basketIdentifier.customerId;
            }

            stateObj.selectedBasket = _.find(billingCustomersData.billingCustomerModels, filter);
        },
        bindEventsBasketCustomersList = function () {
            $("#buttonChangeBasketId").click(function () {
                slideToggleCustomerList();
            });

            $("#changeBasketList li").click(handleClickChangeBillingCustomer);

            $("#buy-options").on("onselectedoption", function (event, optionSelected, selectedAccount) {
                handleSelectedOptionChangeBillingCustomer(optionSelected, selectedAccount);
            });
        },
        restoreSelectedBasketBeforeGiftBasket = function () {
            var billingCustomersData = getBillingCustomersData();
            if (!billingCustomersData || !billingCustomersData.billingCustomerModels) {
                return;
            }

            var newCustomerBasket = _.find(billingCustomersData.billingCustomerModels, { newCustomer: true });
            var previousSelectedBasket = stateObj.selectedBasket || newCustomerBasket;

            if (previousSelectedBasket.buyAsGift) {
                previousSelectedBasket = newCustomerBasket;
            }

            _.each(billingCustomersData.billingCustomerModels, function (bc) {
                if (bc !== previousSelectedBasket) {
                    bc.selected = false;
                    return;
                }

                bc.selected = true;
                basketOperations.setBasketIdentifier({
                    contactId: billingCustomersData.contactId,
                    customerId: bc.id,
                    authenticityIdentifier: billingCustomersData.authId
                });

                if (Util.isUserLogged()) {
                    Util.showComponent.all($("#buttonChangeBasketId"));
                    $(prefixId + getProductId()).addClass("button--3/4");
                    $(prefixId + getProductId()).removeClass("button--1/1");
                }
            });
        },
        selectCorrectBasket = function (optionSelected, selectedAccount) {
            var billingCustomersData = getBillingCustomersData();
            if (!billingCustomersData || !billingCustomersData.billingCustomerModels) {
                return;
            }

            _.each(billingCustomersData.billingCustomerModels, function (bc) {
                switch (optionSelected) {
                    case "buyAsGift":
                        if (!bc.buyAsGift) {
                            bc.selected = false;
                            return;
                        }

                        break;
                    case "associatePayGSubscription":
                        if (bc.id !== selectedAccount.billingCustomerId) {
                            bc.selected = false;
                            return;
                        }

                        break;
                }

                bc.selected = true;
                basketOperations.setBasketIdentifier({
                    contactId: billingCustomersData.contactId,
                    customerId: bc.id,
                    authenticityIdentifier: billingCustomersData.authId
                });
            });

            Util.hideComponent.all($("#changeBasketList"));
            Util.hideComponent.all($("#buttonChangeBasketId"));

            if (Util.isUserLogged()) {
                $(prefixId + getProductId()).removeClass("button--3/4");
                $(prefixId + getProductId()).addClass("button--1/1");
            }
        },
        handleSelectedOptionChangeBillingCustomer = function (optionSelected, selectedAccount) {
            var continueBtn = $(prefixId + getProductId()),
                label;

            if (optionSelected === "buyAsGift" || optionSelected === "associatePayGSubscription") {
                selectCorrectBasket(optionSelected, selectedAccount);

                label = handleLabelButtonAddToBasket(continueBtn.html(), getLayout(), getBillingCustomersData());
                continueBtn.html(label);
            } else {
                restoreSelectedBasketBeforeGiftBasket();
            }

            stateObj.buyAsGift = optionSelected === "buyAsGift";
            stateObj.moveToBillPayFlow = optionSelected === "moveToBillPay";
            stateObj.changeSubscriptionDevice = optionSelected == "associatePayGSubscription";
        },
        changeSelectedBasket = function (customerId, changeBasketButtonActive) {
            var billingCustomersData = getBillingCustomersData();
            if (!billingCustomersData || !billingCustomersData.billingCustomerModels) {
                return;
            }

            if (!changeBasketButtonActive) {
                $("#changeBasketList").hide();
                $("#buttonChangeBasketId").hide();
            } else {
                if (Util.isUserLogged()) {
                    $("#buttonChangeBasketId").show();
                }
            }

            for (var x = 0; x < billingCustomersData.billingCustomerModels.length; x++) {
                var bc = billingCustomersData.billingCustomerModels[x];
                if (bc.id === customerId) {
                    bc.selected = true;
                    stateObj.selectedBasket = bc;
                    break;
                }
            }

            var basketCookie = basketOperations.getBasketCookie();
            basketCookie.customerId = customerId;

            basketOperations.setBasketIdentifier(basketCookie);

            var continueBtn = $(prefixId + getProductId());
            var label = handleLabelButtonAddToBasket(continueBtn.html(), getLayout(), billingCustomersData);

            continueBtn.html(label);
        },
        getCustomerNameSelected = function (selectedBillingCustomer) {
            if (selectedBillingCustomer) {
                if (selectedBillingCustomer.buyAsGift) {
                    return i18n.get("buyAsGiftBasketLabel");
                } else if (selectedBillingCustomer.newCustomer) {
                    return i18n.get("newCustomer");
                } else {
                    return selectedBillingCustomer.name;
                }
            }
        },
        getCurrentBasket = function (billingCustomersData, basketIdentifier) {
            var basket = _.find(billingCustomersData.billingCustomerModels, function (billingCustomer) {
                if (basketIdentifier.customerId === "BUY_AS_GIFT_BASKET") {
                    return billingCustomer.buyAsGift;
                }
                return billingCustomer.selected && !billingCustomer.buyAsGift;
            });

            if (!basket) {
                basket = _.find(billingCustomersData.billingCustomerModels, function (billingCustomer) {
                    return billingCustomer.newCustomer;
                });
            }

            return basket;
        },
        handleLabelButtonAddToBasket = function (label, layout, billingCustomersData) {
            var labelOut = label;
            var basketIdentifier = basketOperations.getBasketCookie();
            var currentSelectedBasket = getCurrentBasket(billingCustomersData, basketIdentifier);
            var name = getCustomerNameSelected(currentSelectedBasket);

            if (layout === CONST.LAYOUT1 && !CONST.PRODUCT_ID_EXCLUDES.includes(stateObj.productId)) {
                if (
                    stateObj.isUpgradeFlow ||
                    stateObj.moveToBillPayFlow ||
                    (currentSelectedBasket && currentSelectedBasket.newCustomer)
                ) {
                    labelOut = i18n.get("labelPrefix") + i18n.get("labelSufix");
                }
            }

            return labelOut;
        },
        getConfigParameters = function (config) {
            var configOut = {
                changeButtonVisible: null,
                defaultDisabled: config ? config.defaultDisabled : false
            };

            var basketIdentifier = basketOperations.getBasketCookie();
            if (
                basketIdentifier &&
                basketIdentifier.customerId &&
                basketIdentifier.customerId === "BUY_AS_GIFT_BASKET"
            ) {
                stateObj.buyAsGift = true;
            }

            if (!Util.isUserLogged() || stateObj.buyAsGift) {
                configOut.changeButtonVisible = false;
            } else {
                if (config) {
                    configOut.changeButtonVisible = config.changeButtonVisible;
                }
            }

            return configOut;
        },
        buildHandlebar = function (productId, layout, label, billingCustomersData, config) {
            var source, template, context, html;
            setProductId(productId);
            setLayout(layout);
            setBillingCustomersData(billingCustomersData);

            label = handleLabelButtonAddToBasket(label, layout, billingCustomersData);
            setLabel(label);

            var params = getConfigParameters(config);

            source = chooseTemplate(layout);
            template = Handlebars.compile(source);
            context = {
                label: label,
                productId: productId,
                billingCustomersData: billingCustomersData,
                changeButtonVisible: params.changeButtonVisible,
                defaultDisabled: params.defaultDisabled
            };
            html = template(context);
            setHtml(html);
        },
        bindEvents = function (parentElementId, webAdd2BasketId, clickCallback, event, triggerCallback) {
            var successCustomerHasDebsCallback = function (data) {
                $(parentElementId).append(getHtml());
                if (!data) {
                    canAddEBU(webAdd2BasketId, function () {
                        bindEventsBasketCustomersList();
                        $(webAdd2BasketId).click(clickCallback);
                        $(webAdd2BasketId).on(event, triggerCallback);
                    });
                } else {
                    $(webAdd2BasketId).click(function (event) {
                        event.preventDefault();
                    });

                    $(webAdd2BasketId).addClass("button--disabled");

                    genericFunctions.showPortalMessage(Granite.I18n.get("vf_basketSummary.WM_BC_10"));
                }
            };

            if (stateObj.isPaygProduct || $("#simOnlyDetails").data("istopupoffer")) {
                skipIsCustomerDebits(successCustomerHasDebsCallback);
            } else {
                isCustomerDebits(successCustomerHasDebsCallback);
            }
        },
        canAddEBU = function (webAdd2BasketId, callback) {
            if (Util.isEBUContext() && Util.isUserLogged() && !Util.isFixedContext()) {
                ajaxRequest.getSpinnerController().start();
                window.omnichannelDataServices.account.getUserAccountCreationDate().then(function (cannotAdd) {
                    ajaxRequest.getSpinnerController().stop();
                    if (cannotAdd) {
                        genericFunctions.refreshPortalMessage(Granite.I18n.get("vf_add2basket.WM_BC_20_blockBasket"));
                        $(webAdd2BasketId).click(function (event) {
                            event.preventDefault();
                        });
                        $(webAdd2BasketId).addClass("button--disabled");
                    } else {
                        callback();
                    }
                });
            } else {
                callback();
            }
        },
        compileHandlebarAccessoryOffer = function (
            parentElement,
            productId,
            layout,
            label,
            billingCustomersData,
            triggerCallback
        ) {
            buildHandlebar(productId, layout, label, billingCustomersData);
            bindEvents(
                "#" + parentElement,
                prefixId + productId,
                clickAddAccessoryOffer,
                CONST.CLICK_ADD_ACCESSORY_OFFER,
                triggerCallback
            );
        },
        compileHandlebarMobileOffer = function (
            parentElement,
            productId,
            layout,
            label,
            billingCustomersData,
            triggerCallback,
            config
        ) {
            buildHandlebar(productId, layout, label, billingCustomersData, config);
            bindEvents(
                "#" + parentElement,
                prefixId + productId,
                clickAddMobileOffer,
                CONST.CLICK_ADD_MOBILE_OFFER,
                triggerCallback
            );
        },
        compileHandlebarFixedOffer = function (
            parentElement,
            productId,
            layout,
            label,
            billingCustomersData,
            triggerCallback
        ) {
            buildHandlebar(productId, layout, label, billingCustomersData);
            bindEvents(
                "#" + parentElement,
                prefixId + productId,
                clickAddFixedOffer,
                CONST.CLICK_ADD_FIXED_OFFER,
                triggerCallback
            );
        },
        compileHandlebarSimOffer = function (
            parentElement,
            productId,
            layout,
            label,
            billingCustomersData,
            triggerCallback
        ) {
            var simoConfig = {
                defaultDisabled: true
            };
            buildHandlebar(productId, layout, label, billingCustomersData, simoConfig);
            bindEvents(
                "#" + parentElement,
                prefixId + productId,
                clickAddSimOffer,
                CONST.CLICK_ADD_SIM_OFFER,
                triggerCallback
            );
        },
        compileHandlebarInsuranceOffer = function (
            parentElement,
            productId,
            layout,
            label,
            billingCustomersData,
            triggerCallback
        ) {
            buildHandlebar(productId, layout, label, billingCustomersData);

            $("#" + productId).html(getHtml());
            $("#" + productId).click(clickAddInsuranceOffer);
            $("#" + productId).on(CONST.CLICK_ADD_INSURANCE_OFFER, triggerCallback);
        },
        compileHandlebarAccessoryOfferMini = function (
            productId,
            layout,
            label,
            billingCustomersData,
            triggerCallback
        ) {
            buildHandlebar(productId, layout, label, billingCustomersData);

            $("#" + productId).html(getHtml());
            $("#" + productId).click(clickAddAccessoryOfferMini);
            $("#" + productId).on(CONST.CLICK_ADD_ACCESSORY_OFFER, triggerCallback);
        },
        isCustomerDebits = function (successIsCustomerDebits) {
            if (!isCheckedCustomerDebits) {
                var successCustomerDebsCallback = function (data) {
                    customerHasDebs = data;
                    successIsCustomerDebits(customerHasDebs);
                };

                var errorCustomerDebsCallback = function () {
                    if (isMobileOffer) {
                        var productDetailsDatalayer = new ProductDetailsDatalayer(),
                            errorMessage = "Error getting account collection status (GET /accounts/collectionstatus)";
                        productDetailsDatalayer.setErrorEvent(errorMessage, true);
                    }
                    ajaxRequest.getSpinnerController().stop();
                };

                var callbackAlways = function () {
                    ajaxRequest.getSpinnerController().stop();
                };

                ajaxRequest.getSpinnerController().start();
                ajaxRequest.getAlways(
                    "/accounts/collectionstatus",
                    successCustomerDebsCallback,
                    errorCustomerDebsCallback,
                    callbackAlways
                );
                isCheckedCustomerDebits = true;
            } else {
                successIsCustomerDebits(customerHasDebs);
            }
        },
        skipIsCustomerDebits = function (successCustomerHasDebsCallback) {
            successCustomerHasDebsCallback(false);
        },
        validateParameters = function (layout, label) {
            if (label) {
                setLabel(label);
            }

            if (layout) {
                setLayout(layout);
            }
        },
        init = function (callbackSuccess, callbackError) {
            cartMini.loadBillingCustomerData(callbackSuccess, callbackError);
        },
        handleBillingCustomerData = function (data) {
            if (data.processContKey) {
                basketOperations.setBasketIdentifier(data.processContKey);
            }

            var basketIdentifier = basketOperations.getBasketCookie();
            var isEdit = window.location.href.indexOf("mode=edit") !== -1;
            if (
                basketIdentifier &&
                basketIdentifier.customerId &&
                basketIdentifier.customerId === "BUY_AS_GIFT_BASKET" &&
                !isEdit
            ) {
                basketOperations.resetBasketIdentifierCustomer(basketIdentifier);
            }

            // get selected basket by default
            if (data && data.billingCustomerModels) {
                stateObj.selectedBasket = _.find(data.billingCustomerModels, {
                    selected: true
                });
            }

            return {
                billingCustomerModels: data.billingCustomerModels,
                contactId: data.contactId,
                labels: {
                    newCustomerLabel: i18n.get("newCustomer"),
                    changeBasket: i18n.get("changeBasket"),
                    buyAsGiftBasketLabel: i18n.get("buyAsGiftBasketLabel")
                }
            };
        },
        initAccessoryOffer = function (parentElement, productId, layout, label, triggerCallback) {
            var successCallback = function (response) {
                    validateParameters(layout, label);
                    compileHandlebarAccessoryOffer(
                        parentElement,
                        productId,
                        getLayout(),
                        getLabel(),
                        handleBillingCustomerData(response),
                        triggerCallback
                    );
                },
                errorCallbask = function () {};

            if (layout === CONST.LAYOUT1) {
                init(successCallback, errorCallbask);
            } else {
                validateParameters(layout, label);
                compileHandlebarAccessoryOffer(
                    parentElement,
                    productId,
                    getLayout(),
                    getLabel(),
                    null,
                    triggerCallback
                );
            }
        },
        initAccessoryOfferMini = function (productId, layout, label, triggerCallback) {
            var successCallback = function (response) {
                    validateParameters(layout, label);
                    compileHandlebarAccessoryOfferMini(
                        productId,
                        getLayout(),
                        getLabel(),
                        handleBillingCustomerData(response),
                        triggerCallback
                    );
                },
                errorCallbask = function () {};

            if (layout === CONST.LAYOUT1) {
                init(successCallback, errorCallbask);
            } else {
                validateParameters(layout, label);
                compileHandlebarAccessoryOfferMini(productId, getLayout(), getLabel(), null, triggerCallback);
            }
        },
        initMobileOffer = function (parentElement, productId, layout, label, triggerCallback, config) {
            var successCallback = function (response) {
                    validateParameters(layout, label);
                    isMobileOffer = true;
                    compileHandlebarMobileOffer(
                        parentElement,
                        productId,
                        getLayout(),
                        getLabel(),
                        handleBillingCustomerData(response),
                        triggerCallback,
                        config
                    );
                },
                errorCallbask = function () {};

            if (layout === CONST.LAYOUT1) {
                init(successCallback, errorCallbask);
            } else {
                validateParameters(layout, label);
                compileHandlebarMobileOffer(parentElement, productId, getLayout(), getLabel(), null, triggerCallback);
            }
        },
        initFixedOffer = function (parentElement, productId, layout, label, triggerCallback) {
            var successCallback = function (response) {
                    setProcessContKey(response.processContKey);
                    setBillingCustomersData(response);
                    validateParameters(layout, label);
                    compileHandlebarFixedOffer(
                        parentElement,
                        productId,
                        getLayout(),
                        getLabel(),
                        handleBillingCustomerData(response),
                        triggerCallback
                    );
                },
                errorCallbask = function () {};

            if (layout === CONST.LAYOUT1) {
                init(successCallback, errorCallbask);
            } else {
                validateParameters(layout, label);
                compileHandlebarFixedOffer(parentElement, productId, getLayout(), getLabel(), null, triggerCallback);
            }
        },
        initSimOffer = function (parentElement, productId, layout, label, triggerCallback) {
            var successCallback = function (response) {
                    validateParameters(layout, label);
                    compileHandlebarSimOffer(
                        parentElement,
                        productId,
                        getLayout(),
                        getLabel(),
                        handleBillingCustomerData(response),
                        triggerCallback
                    );

                    ajaxRequest.getSpinnerController().stop();
                },
                errorCallbask = function () {
                    ajaxRequest.getSpinnerController().stop();
                };

            if (layout === CONST.LAYOUT1) {
                ajaxRequest.getSpinnerController().start();
                init(successCallback, errorCallbask);
            } else {
                validateParameters(layout, label);
                compileHandlebarSimOffer(parentElement, productId, getLayout(), getLabel(), null, triggerCallback);
            }
        },
        initInsuranceOffer = function (parentElement, productId, layout, label, triggerCallback) {
            console.log(productId, layout, label, triggerCallback);
            var successCallback = function (response) {
                    validateParameters(layout, label);
                    compileHandlebarInsuranceOffer(
                        parentElement,
                        productId,
                        getLayout(),
                        getLabel(),
                        handleBillingCustomerData(response),
                        triggerCallback
                    );
                },
                errorCallbask = function () {};

            if (layout === CONST.LAYOUT1) {
                init(successCallback, errorCallbask);
            } else {
                validateParameters(layout, label);
                compileHandlebarInsuranceOffer(productId, getLayout(), getLabel(), null, triggerCallback);
            }
        };

    return {
        LAYOUT1: CONST.LAYOUT1,
        LAYOUT2: CONST.LAYOUT2,
        LAYOUT3: CONST.LAYOUT3,
        setStateObj: setStateObj,
        copyStateObj: copyStateObj,
        getProductId: getProductId,
        setProductId: setProductId,
        getLabel: getLabel,
        setLabel: setLabel,
        getLayout: getLayout,
        setLayout: setLayout,
        getTemplateId: getTemplateId,
        setTemplateId: setTemplateId,
        getHtml: getHtml,
        setHtml: setHtml,
        getDevice: getDevice,
        setDevice: setDevice,
        setOneNumberAccessories: setOneNumberAccessories,
        getPrimaryPlan: getPrimaryPlan,
        setPrimaryPlan: setPrimaryPlan,
        getAdditionalPlans: getAdditionalPlans,
        setAdditionalPlans: setAdditionalPlans,
        getBroadbandOffer: getBroadbandOffer,
        setBroadbandOffer: setBroadbandOffer,
        getLandlineOffer: getLandlineOffer,
        setLandlineOffer: setLandlineOffer,
        getTvOffer: getTvOffer,
        setTvOffer: setTvOffer,
        getSim: getSim,
        setSim: setSim,
        getOfferId: getOfferId,
        setOfferId: setOfferId,
        getPlanId: getPlanId,
        setPlanId: setPlanId,
        getBundleId: getBundleId,
        setBundleId: setBundleId,
        getInsurance: getInsurance,
        setInsurance: setInsurance,
        getAddOns: getAddOns,
        setAddOns: setAddOns,
        getCampaign: getCampaign,
        setCampaign: setCampaign,
        getCustomerId: getCustomerId,
        setCustomerId: setCustomerId,
        getAccessories: getAccessories,
        setAccessories: setAccessories,
        setUpgradeFlow: setUpgradeFlow,
        getUpgradeFlow: getUpgradeFlow,
        initAccessoryOffer: initAccessoryOffer,
        initAccessoryOfferMini: initAccessoryOfferMini,
        initMobileOffer: initMobileOffer,
        initFixedOffer: initFixedOffer,
        initSimOffer: initSimOffer,
        initInsuranceOffer: initInsuranceOffer,
        addAccessoryOfferMini: addAccessoryOfferMini,
        addAccessoryOffer: addAccessoryOffer,
        addMobileOffer: addMobileOffer,
        addFixedOffer: addFixedOffer,
        addFixedOfferById: addFixedOfferById,
        addSimOffer: addSimOffer,
        addSimOfferById: addSimOfferById,
        addInsuranceOffer: addInsuranceOffer,
        isCustomerDebits: isCustomerDebits,
        changeMobileOffer: changeMobileOffer,
        changeBundleOffer: changeBundleOffer,
        addCampaign: addCampaign,
        changePlanAndAddCampaign: changePlanAndAddCampaign,
        enableAdd2Basket: enableAdd2Basket,
        moveToBillPay: moveToBillPay,
        changeSelectedBasket: changeSelectedBasket,
        setIsTopUpOffer: setIsTopUpOffer,
        isTopUpOffer: isTopUpOffer,
        setIsPaygProduct: setIsPaygProduct,
        setIsFixedVoice: setIsFixedVoice,
        getFixedVoice: getFixedVoice,
        setUAN: setUAN,
        getUAN: getUAN,
        getBasketURL: getBasketURL,
        checkBasketForLoggedInUser: checkBasketForLoggedInUser,
        setMBB: setMBB,
        replaceStandaloneOffer: replaceStandaloneOffer,
        stateObj: stateObj
    };
};

/*global $, DataLayer, utag_data, utag*/
var add2BasketDatalayer = (function () {

    var pageEventAnalysis = 'event_name',
        createCartAnalysis = 'cart_date_start',
        updateCartAnalysis = 'cart_date_update',

        setAddCart = function () {
            DataLayer.updateAttribute(({
                name: pageEventAnalysis,
                value: 'cart_add'
            }), true);
            setEventCart();
        },

        setCreateCartDate = function (date) {
            DataLayer.updateAttribute(({
                name: createCartAnalysis,
                value: date
            }), true);
        },

        setUpdateCartDate = function (date) {
            DataLayer.updateAttribute(({
                name: updateCartAnalysis,
                value: date
            }), true);
        },

        setEventCart = function () {
            DataLayer.updateAttribute(({
                name: pageEventAnalysis,
                value: 'event'
            }), true);
            DataLayer.removeAttributeUtagData(pageEventAnalysis);
        };

    return {
        setAddCart: setAddCart,
        setCreateCartDate: setCreateCartDate,
        setUpdateCartDate: setUpdateCartDate
    };
}());

