ACC.threeDSecure = {

    is3DSecureEnabledForHostedFields: function(payload) {
        if (threeDSecureFlow === CONST.DISABLED) {
            return false;
        } else if (threeDSecureFlow === CONST.ALWAYS) {
            return true;
        } else if (threeDSecureFlow === CONST.AUTO) {
            const environment = payload.authenticationInsight.regulationEnvironment;
            if (environment === 'psd2' || environment === 'unavailable') {
                return true;
            } else {
                return false;
            }
        }
    },

    is3DSecureEnabledForGooglePay: function() {
        return threeDSecureFlow !== CONST.DISABLED;
    },

    isExpressCheckoutPage: function() {
        return typeof cartPage != 'undefined' ||
         typeof cartPopup != 'undefined' ||
         typeof addToCartPopup != 'undefined';
    },

    inferContainerIdByPage: function() {
       if (typeof cartPopup != 'undefined' && cartPopup != '') {
           return'cart-pop-up-container';
       } else if (typeof cartPage != 'undefined') {
           return 'cart-page-container';
       } else if (typeof addToCartPopup != 'undefined') {
           return 'add-to-cart-pop-up-container';
       } else if (typeof accountPage != 'undefined') {
           return 'add-payment-method-page-container';
       } else if (typeof paymentMethodsPage != "undefined") {
           return "silent-order-post-page-container";
       }
    },

    verifySavedPaymentBy3DSecure: function(e) {
        e.preventDefault();
        var paymentMethodId = $(e.target).find('input[name="selectedPaymentMethodId"]').val();
        var paymentMethod = $(e.target).find('input[name="selectedPaymentMethod"]').val();
        if (paymentMethod === "PayPal" || paymentMethod === 'notFor3DSecure') {
            e.currentTarget.submit();
        }

        var processUrl = ACC.config.encodedContextPath + '/braintree/checkout/hop/getNewNonce';
        var params = {
          "paymentMethodId": paymentMethodId
        };

        $.get(processUrl, params)
        .then((paymentNonceResponse) => {

            if(paymentNonceResponse.shouldPerform3dSecure) {

                braintree.client.create({
                  authorization: clientToken
                }, function (clientErr, clientInstance) {

                    if (clientErr) {
                        $("#submit_silentOrderPostForm").removeAttr("disabled");
                        handleClientError(clientErr);
                        return;
                    }
                    braintree.threeDSecure.create({
                      version: 2,
                      client: clientInstance
                    }, function (err, threeDSecure) {
                        ACC.threeDSecure.requestAdditionalFields(
                            threeDSecure,
                            paymentNonceResponse,
                            undefined,
                            undefined,
                            e
                        )
                    });
                });

            } else {
                if (verifyFlow === true && paymentMethod === "creditCardPaymentMethod") {
                    ACC.creditCard.verifyCVV(e);
                } else {
                    e.currentTarget.submit();
                }
            }

        });
        return false;
    },

    verifyHostedFieldsBy3DSecure: function(clientInstance, paymentResponse) {
        ACC.threeDSecure.createThreeDSecure(clientInstance, paymentResponse);
    },

    verifyGooglePayBy3DSecureOnExpressCheckout: function(paymentResponse, googlePayPaymentData, isMiniCartCheckout) {
        braintree.client.create({
            authorization: clientToken
        }, function (clientErr, clientInstance) {
            braintree.threeDSecure.create({
                version: 2,
                client: clientInstance
            }, function (err, threeDSecure) {
               ACC.threeDSecure.requestAdditionalFieldsForExpressCheckout(threeDSecure, paymentResponse, googlePayPaymentData, isMiniCartCheckout);
            });
        });
    },

    verifyGooglePayBy3DSecure: function(paymentResponse, googlePayPaymentData, isMiniCartCheckout) {
            braintree.client.create({
                authorization: clientToken
            }, function (clientErr, clientInstance) {
                ACC.threeDSecure.createThreeDSecureForGooglePay(clientInstance, paymentResponse, googlePayPaymentData, isMiniCartCheckout);
            });
    },

    createThreeDSecure: function(clientInstance, paymentResponse, googlePayPaymentData, isMiniCartCheckout) {
        braintree.threeDSecure.create({
            version: 2,
            client: clientInstance
        }, function (err, threeDSecure) {
            if (pageType !== 'undefined' && pageType === 'account') {
                ACC.threeDSecure.perform3DS(threeDSecure, paymentResponse, prepareAddressData());
            } else {
                ACC.threeDSecure.requestAdditionalFields(threeDSecure, paymentResponse);
            }
        });
    },

    createThreeDSecureForGooglePay: function(clientInstance, paymentResponse, googlePayPaymentData, isMiniCartCheckout) {
        braintree.threeDSecure.create({
            version: 2,
            client: clientInstance
        }, function (err, threeDSecure) {
            if (pageType !== 'undefined' && pageType === 'account') {
                ACC.threeDSecure.perform3DS(
                    threeDSecure,
                    paymentResponse,
                    googlePayPaymentData.paymentMethodData.info.billingAddress,
                    googlePayPaymentData,
                    isMiniCartCheckout
                );
            } else {
                ACC.threeDSecure.requestAdditionalFields(
                    threeDSecure,
                    paymentResponse,
                    googlePayPaymentData,
                    isMiniCartCheckout
                );
            }
        });
    },

    perform3DS: function(threeDSecure, paymentResponse, address, googlePayPaymentData, isMiniCartCheckout, e) {
        var data;
        var pageContainerId;
        if (pageType === 'account' || pageType === 'undefined') {
            data = ACC.threeDSecure.get3DSVerificationDataForMyAccountPage(paymentResponse, address);
            pageContainerId = 'add-payment-method-page-container';
        } else {
            data = ACC.threeDSecure.get3DSVerificationData(paymentResponse, address);
            pageContainerId = 'silent-order-post-page-container';
        }
        ACC.loadingSpinner.showSpinner(pageContainerId);
        threeDSecure.verifyCard(data,
            function (error, response) {
                if (error) {
                    ACC.loadingSpinner.hideSpinner(ACC.threeDSecure.inferContainerIdByPage());
                    ACC.generalUtil.showErrorMessage(error);
                    $("#submit_silentOrderPostForm").removeAttr("disabled");
                    $("button[id^='useSelectedPaymentMethod']").removeAttr("disabled");
                    return;
                }
                // 3DSecure finished, add 3DSecure returned nonce
                var liabilityShifted = response.liabilityShifted;
                var liabilityShiftPossible = response.liabilityShiftPossible;
                // allow process card if 3dSecureLiabilityResult is
                // skipped by merchant
                if (liabilityShifted || !liabilityShiftPossible) {
                    if (e !== undefined) {
                        $(e.target).find('input[name="selectedPaymentMethodNonce"]').val(response.nonce);
                        $(e.target).find('input[name="is3dSecureFlow"]').val('true');
                        var paymentMethod = $(e.target).find('input[name="selectedPaymentMethod"]').val();

                        if (verifyFlow && paymentMethod === "creditCardPaymentMethod") {
                          ACC.creditCard.verifyCVV(e);
                        } else {
                          e.currentTarget.submit();
                        }
                    } else {
                        paymentResponse.nonce = response.nonce;
                        paymentResponse.liabilityShifted = liabilityShifted;
                        paymentResponse.liabilityShiftPossible = liabilityShiftPossible;
                        paymentResponse.is3dSecureFlow = true;
                        if (response.type === "AndroidPayCard") {
                            processGooglePayResponse(paymentResponse, googlePayPaymentData, isMiniCartCheckout)
                        } else {
                            processResponse(paymentResponse);
                        }

                    }
                } else {
                    ACC.loadingSpinner.hideSpinner(pageContainerId);
                    $("#submit_silentOrderPostForm").removeAttr("disabled");
                    $("button[id^='useSelectedPaymentMethod']").removeAttr("disabled");
                    ACC.generalUtil.showErrorMessage(ACC.addons.braintreeb2baddon['braintree.message.unsecured.card']);
                }

            }
        );
    },

    perform3DSOnExpressCheckout: function(threeDSecure, paymentResponse, address, googlePayPaymentData, isMiniCartCheckout, e) {
        var data = ACC.threeDSecure.get3DSVerificationData(paymentResponse, address);
        var pageContainerId = ACC.threeDSecure.inferContainerIdByPage();
        ACC.loadingSpinner.showSpinner(pageContainerId);
        threeDSecure.verifyCard(data,
            function (error, response) {
                if (error) {
                    ACC.loadingSpinner.hideSpinner(pageContainerId);
                    ACC.generalUtil.showErrorMessage(error);
                    return;
                }
                var liabilityShifted = response.liabilityShifted;
                var liabilityShiftPossible = response.liabilityShiftPossible;
                if (liabilityShifted || !liabilityShiftPossible) {
                    paymentResponse.nonce = response.nonce;
                    processGooglePayResponse(paymentResponse, googlePayPaymentData, isMiniCartCheckout);
                } else {
                    ACC.loadingSpinner.hideSpinner(pageContainerId);
                    ACC.generalUtil.showErrorMessage(ACC.addons.braintreeb2baddon['braintree.message.unsecured.card']);
                }
            }
        );
    },

    requestAdditionalFieldsForExpressCheckout: function(threeDSecure, paymentResponse, googlePayPaymentData, isMiniCartCheckout, e) {
        var additionalInfoUrl = ACC.config.encodedContextPath + '/braintree/checkout/hop/getAdditionalInfo';
        $.get(additionalInfoUrl)
          .then((additionalInformation) => ACC.threeDSecure.perform3DSOnExpressCheckout(threeDSecure, paymentResponse, additionalInformation, googlePayPaymentData, isMiniCartCheckout, e));
    },

    requestAdditionalFields: function(threeDSecure, paymentResponse, googlePayPaymentData, isMiniCartCheckout, e) {
        var additionalInfoUrl = ACC.config.encodedContextPath + '/braintree/checkout/hop/getAdditionalInfo';
        $.get(additionalInfoUrl)
          .then((additionalInformation) => ACC.threeDSecure.perform3DS(threeDSecure, paymentResponse, additionalInformation, googlePayPaymentData, isMiniCartCheckout, e));
    },

    getBillingAddressFor3DS: function(address) {
        var billingAddress = {};
        if (!address) {
            var givenName = document.getElementById('address.firstName');
            var surname = document.getElementById('address.surname');
            var phoneNumber = document.getElementById('address.phone');
            var streetAddress = document.getElementById('address.line1');
            var extendedAddress = document.getElementById('address.line2');
            var locality = document.getElementById('address.townCity');
            var region = document.getElementById('address.region');
            var postalCode = document.getElementById('address.postcode');
            var countryCodeAlpha2 = document.getElementById('address.country');

            if (givenName !== null) {
                billingAddress.givenName = givenName.value;
            }
            if (surname !== null) {
                billingAddress.surname = surname.value;
            }
            if (phoneNumber !== null) {
                billingAddress.phoneNumber = phoneNumber.value;
            }
            if (streetAddress !== null) {
                billingAddress.streetAddress = streetAddress.value;
            }
            if (extendedAddress !== null) {
                billingAddress.extendedAddress = extendedAddress.value;
            }
            if (locality !== null) {
                billingAddress.locality = locality.value;
            }
            if (region !== null) {
                billingAddress.region = region.value;
            }
            if (postalCode !== null) {
                billingAddress.postalCode = postalCode.value;
            }
            if (countryCodeAlpha2 !== null) {
                billingAddress.countryCodeAlpha2 = countryCodeAlpha2.value;
            }
        } else {
            billingAddress.givenName = address.firstName;
            billingAddress.surname = address.lastName;
            billingAddress.phoneNumber = address.phone;
            billingAddress.streetAddress = address.line1;
            billingAddress.extendedAddress = address.line2;
            billingAddress.locality = address.town;
            billingAddress.postalCode = address.postalCode;
            billingAddress.countryCodeAlpha2 = address.country?.isocode;
            if (address.region !== null){
                billingAddress.region = address.region?.isocodeShort;
            }
        }

        return billingAddress;
    },

    get3DSVerificationDataForMyAccountPage: function(paymentResponse, address) {
        if (address === 'string') {
            var address = JSON.parse(address);
        }
        var data =  {
            onLookupComplete: function (data, next) {
                next();
            },
            amount: '0',
            nonce: paymentResponse.nonce,
            bin: paymentResponse.details.bin,
            challengeRequested: threeDSecureChallengeRequested,
            addFrame: (err, iframe) => ACC.threeDSecure.addFrameFunction(err, iframe),
            removeFrame: function () {
                ACC.colorbox.close();
            },
            billingAddress: {
                givenName: address.firstName,
                surname: address.lastName,
                phoneNumber: address.phone,
                streetAddress: address.line1,
                extendedAddress: address.line2,
                locality: address.townCity,
                postalCode: address.postcode,
                countryCodeAlpha2: address.countryIso
            }
        };

        return data;
    },

    get3DSVerificationData: function(paymentResponse, additionalInformation) {
        var data =  {
            onLookupComplete: function (data, next) {
                next();
            },
            amount: amount,
            nonce: paymentResponse.nonce,
            bin: paymentResponse.details.bin,
            challengeRequested: threeDSecureChallengeRequested,
            addFrame: (err, iframe) => ACC.threeDSecure.addFrameFunction(err, iframe),
            removeFrame: function () {
                ACC.colorbox.close();
            },
            billingAddress: ACC.threeDSecure.getBillingAddressFor3DS(paymentResponse.billingAddress),
        }
        if (!threeDSecureChallengeRequested && threeDSecureSCAExemption !== CONST.DISABLED) {
            data.requestedExemptionType = threeDSecureSCAExemption.toLowerCase();
        }

        if (additionalInformation !== null) {
            data.email = additionalInformation.email;
            data.additionalInformation = {
                workPhoneNumber: additionalInformation.phone,
                shippingGivenName: additionalInformation.firstName,
                shippingSurname: additionalInformation.lastName,
                shippingPhone: additionalInformation.phone,
                shippingAddress: {
                    streetAddress: additionalInformation.line1,
                    extendedAddress: additionalInformation.line2,
                    locality: additionalInformation.town,
                    postalCode: additionalInformation.postalCode,
                    countryCodeAlpha2: additionalInformation.country?.isocode
                }
            }
            if (additionalInformation.region !== null) {
                data.additionalInformation.shippingAddress.region = additionalInformation.region?.isocodeShort;
            }
        }

        return data;
    },

    addFrameFunction: function(err,iframe) {
        const threeDSContainer = $(HTML.DIV);
        $(threeDSContainer).append(iframe);
        ACC.colorbox.open("", {
            inline: true,
            href: threeDSContainer,
            onComplete: function () {
                $(this).colorbox.resize();
            }
        });
    }
}