@addTagHelper *, BundlerMinifier.TagHelpers
@inject BTCPayServer.Services.LanguageService langService
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
@model PaymentModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <META NAME="robots" CONTENT="noindex,nofollow">
    <title>@Model.HtmlTitle</title>

    <bundle name="wwwroot/bundles/checkout-bundle.min.css" />

    <script type="text/javascript">
        var initialSrvModel = @Safe.Json(Model);
    </script>

    <bundle name="wwwroot/bundles/checkout-bundle.min.js" />
    <script>vex.defaultOptions.className = 'vex-theme-btcpay'</script>

    @if (Model.CustomCSSLink != null)
    {
        <link href="@Model.CustomCSSLink" rel="stylesheet" />
    }

    @if (Model.IsModal)
    {
        <style type="text/css">
            body {
                background: rgba(55, 58, 60, 0.4);
            }

            .close-icon {
                display: flex;
            }
        </style>
    }
</head>
<body>
    <noscript>
        <center style="padding: 2em">
            <h2>Javascript is currently disabled in your browser.</h2>
            <h5>Please enable Javascript and refresh this page for the best experience.</h5>

            <p>Alternatively, click below to continue to our HTML-only invoice.</p>

            <a href="/invoice-noscript?id=@Model.InvoiceId" style="text-decoration: underline; color: blue">
                Continue to javascript-disabled invoice &gt;
            </a>
        </center>
    </noscript>

    <!--[if lte IE 8]>
    <center style="padding: 2em">
      <form action="/invoice-noscript" method="GET">
        <button style="text-decoration: underline; color: blue">Continue to legacy browser compatible invoice page
        </button>
      </form>
    </center>
    <![endif]-->

    <invoice>
        <div class="no-bounce" id="checkoutCtrl" v-cloak>
            <div class="modal page">
                <div class="modal-dialog open opened" role="document" v-bind:class="{ 'expired': invoiceUnpayable, 'paid': invoicePaid, 'enter-purchaser-email': showEmailForm}">
                    <div class="modal-content long">
                        <div class="content">
                            <div class="invoice">
                                <partial name="Checkout-Body" />
                            </div>
                        </div>
                    </div>

                    <div style="margin-top: 10px; text-align: center;">
                        @* Not working because of nsSeparator: false, keySeparator: false,
                            {{$t("nested.lang")}} >>
                        *@

                        <select asp-for="DefaultLang"
                                class="cmblang reverse invisible"
                                onkeypress="if(event.keyCode==13){ $(this).click();}"
                                onchange="changeLanguage($(this).val())"
                                asp-items="@langService.GetLanguages().Select((language) => new SelectListItem(language.DisplayName,language.Code, false))"></select>

                        <script>
                            var languageSelectorPrettyDropdown;
                            $(function () {
                                // REVIEW: don't use initDropdown method but rather directly initialize select whenever you are using it
                                $("#DefaultLang").val(startingLanguage);
                                languageSelectorPrettyDropdown = initDropdown("#DefaultLang");
                            });

                            function initDropdown(selector) {
                                return $(selector).prettyDropdown({
                                    classic: false,
                                    height: 32,
                                    reverse: true,
                                    hoverIntent: 5000
                                });
                            }
                        </script>
                    </div>
                    <div style="margin-top: 10px; text-align: center;" class="form-text small text-muted">
                        <span>Powered by <a target="_blank" href="https://github.com/btcpayserver/btcpayserver">BTCPay Server</a></span>
                    </div>
                </div>
            </div>
        </div>
    </invoice>
    <script type="text/javascript">
    var availableLanguages = @Safe.Json(langService.GetLanguages().Select((language) => language.Code));;
    var storeDefaultLang = @Safe.Json(@Model.DefaultLang);
    var fallbackLanguage = "en";
    startingLanguage = computeStartingLanguage();
    i18next
        .use(window.i18nextXHRBackend)
        .init({
            backend: {
                loadPath: @Safe.Json($"{Model.RootPath}locales/{{{{lng}}}}.json")
            },
            lng: startingLanguage,
            fallbackLng: fallbackLanguage,
            nsSeparator: false,
            keySeparator: false
        });

    function computeStartingLanguage() {
        if (urlParams.lang && isLanguageAvailable(urlParams.lang)) {
            return urlParams.lang;
        }
        else if (isLanguageAvailable(storeDefaultLang)) {
            return storeDefaultLang;
        } else {
            return fallbackLanguage;
        }
    }

    function changeLanguage(lang) {
        if (isLanguageAvailable(lang)) {
            i18next.changeLanguage(lang);
        }
    }

    function isLanguageAvailable(languageCode) {
        return availableLanguages.indexOf(languageCode) >= 0;
    }

    var i18n = new VueI18next(i18next);
    Vue.config.ignoredElements = [
        'line-items',
        'low-fee-timeline',
        // Ignoring custom HTML5 elements, eg: bp-spinner
        /^bp-/
    ];
    var eventBus = new Vue();
    var checkoutCtrl = new Vue({
        i18n: i18n,
        el: '#checkoutCtrl',
        data: {
            srvModel: initialSrvModel,
            end: new Date(),
            expirationPercentage: 0,
            timerText: "@Model.TimeLeft",
            emailAddressInput: "",
            emailAddressInputDirty: false,
            emailAddressInputInvalid: false,
            emailAddressFormSubmitting: false,
            lineItemsExpanded: false,
            changingCurrencies: false,
            loading: true,
            isModal: initialSrvModel.isModal
        },
        computed: {
            expiringSoon: function(){
                return this.expirationPercentage >= 75 && !this.invoiceUnpayable && !this.invoicePaid;
            },
            showPaymentUI: function(){
                return !this.showEmailForm && !this.invoiceUnpayable && !this.invoicePaid;
            },
            showEmailForm: function(){
                return this.srvModel.requiresRefundEmail && (!this.srvModel.customerEmail || !this.validateEmail(this.srvModel.customerEmail)) && !this.invoiceUnpayable && !this.invoicePaid;
            },
            showRecommendedFee: function(){
                return  this.srvModel.showRecommendedFee && this.srvModel.feeRate != 0;
            },
            invoiceUnpayable: function(){
                return  ["expired", "invalid"].indexOf(this.srvModel.status) >= 0;
            },
            invoicePaid: function(){
                return  ["complete", "confirmed", "paid"].indexOf(this.srvModel.status) >= 0;
            }
        },
        mounted: function(){
            this.startProgressTimer();
            this.listenIn();
            this.onDataCallback(this.srvModel);
            if (this.srvModel.status === "new" && this.srvModel.txCount > 1) {
                this.onlyExpandLineItems();
            }
            window.parent.postMessage("loaded", "*");
            jQuery("invoice").fadeOut(0).fadeIn(300);
            window.closePaymentMethodDialog = this.closePaymentMethodDialog.bind(this);
            this.loading = false;
        },
        methods: {
            onlyExpandLineItems: function() {
                if (!this.lineItemsExpanded) {
                    this.toggleLineItems();
                }},
            toggleLineItems: function() {
                this.lineItemsExpanded ? $("line-items").slideUp() : $("line-items").slideDown();
                this.lineItemsExpanded = !this.lineItemsExpanded;
            },
            openPaymentMethodDialog: function() {
                var content = $("#vexPopupDialog").html();
                vex.open({
                    unsafeContent: content
                });
            },
            closePaymentMethodDialog: function(currencyId) {
                vex.closeAll();
                this.changeCurrency(currencyId);
            },   
            changeCurrency: function (currency) {
                if (currency !== null && this.srvModel.paymentMethodId !== currency) {
                    this.changingCurrencies = true;
                    this.srvModel.paymentMethodId = currency;
                    this.fetchData();
                    this.closePaymentMethodDialog(null);
                }
            },     
            close: function(){
                $("invoice").fadeOut(300, function () {
                    window.parent.postMessage("close", "*");
                });
            },
            validateEmail: function (email) {
                var re = /^(([^<>()\[\]\\.,;:\s@@"]+(\.[^<>()\[\]\\.,;:\s@@"]+)*)|(".+"))@@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
                return re.test(email);
            },
            startProgressTimer: function(){
                var timeLeftS = this.endDate? (this.endDate.getTime() - new Date().getTime())/1000 : this.srvModel.expirationSeconds;
                this.expirationPercentage = 100 - ((timeLeftS / this.srvModel.maxTimeSeconds) * 100);
                this.timerText = this.updateTimerText(timeLeftS);
                if( this.expirationPercentage < 100 &&  (this.srvModel.status === "paidPartial" || this.srvModel.status === "new")){
                    setTimeout(this.startProgressTimer, 500);
                }
            },
            updateTimerText: function (timer) {
                if (timer >= 0) {
                    var minutes = parseInt(timer / 60, 10);
                    minutes = minutes < 10 ? "0" + minutes : minutes;
                    var seconds = parseInt(timer % 60, 10);
                    seconds = seconds < 10 ? "0" + seconds : seconds;
                    return minutes + ":" + seconds;
                } else {
                    return "00:00";
                }
            },
            listenIn: function(){
                var self = this;
                var socket = null;
                var supportsWebSockets = 'WebSocket' in window && window.WebSocket.CLOSING === 2;
                if (supportsWebSockets) {
                    var loc = window.location, ws_uri;
                    if (loc.protocol === "https:") {
                        ws_uri = "wss:";
                    } else {
                        ws_uri = "ws:";
                    }
                    ws_uri += "//" + loc.host;
                    ws_uri += loc.pathname + "/status/ws?invoiceId=" + this.srvModel.invoiceId;
                    try {
                        socket = new WebSocket(ws_uri);
                        socket.onmessage = function (e) {
                            self.fetchData();
                        };
                        socket.onerror = function (e) {
                            console.error("Error while connecting to websocket for invoice notifications (callback)");
                        };
                    }
                    catch (e) {
                        console.error("Error while connecting to websocket for invoice notifications");
                    }
                }
                var self = this;
                function watcher(){
                    setTimeout(function(){
                        if (socket === null || socket.readyState !== 1) {
                            self.fetchData();
                        }
                        watcher();
                    }, 2000);
                }            
                watcher();
            },
            fetchData: function(){
                var self = this;
                $.ajax({
                    url: window.location.pathname + "/status?invoiceId=" + this.srvModel.invoiceId + "&paymentMethodId=" + this.srvModel.paymentMethodId,
                    type: "GET",
                    cache: false
                })
                .done(function (data) {
                    self.onDataCallback.bind(self)(data);
                })
            },
            onDataCallback : function(jsonData){
                if (this.srvModel.status !== jsonData.status) {
                    window.parent.postMessage({ "invoiceId": this.srvModel.invoiceId, "status": jsonData.status }, "*");
                }
                if (jsonData.paymentMethodId === this.srvModel.paymentMethodId) {
                    this.changingCurrencies = false;
                }
                // displaying satoshis for lightning payments
                jsonData.cryptoCodeSrv = jsonData.cryptoCode;
                // expand line items to show details on amount due for multi-transaction payment
                if (this.srvModel.txCount === 1 && jsonData.txCount > 1) {
                    this.onlyExpandLineItems();
                }
                var newEnd = new Date();
                newEnd.setSeconds(newEnd.getSeconds()+ jsonData.expirationSeconds);
                this.endDate = newEnd;
                // updating ui
                this.srvModel = jsonData;
                if (this.invoicePaid && !jsonData.isModal && jsonData.redirectAutomatically && jsonData.merchantRefLink) {
                    this.loading = true;
                    setTimeout(function () {
                        window.location = jsonData.merchantRefLink;
                    }, 2000);
                }
            },
            onEmailChange: function(){
                this.emailAddressInputDirty = true;
                this.emailAddressInputInvalid = false;
            },
            onEmailSubmit : function(){
                var self = this;
                if (this.validateEmail(this.emailAddressInput)) {
                    this.emailAddressFormSubmitting = true;
                    // Push the email to a server, once the reception is confirmed move on
                    $.ajax({
                        url: window.location.pathname + "/UpdateCustomer?invoiceId=" +this.srvModel.invoiceId,
                        type: "POST",
                        data: JSON.stringify({ Email: this.emailAddressInput }),
                        contentType: "application/json; charset=utf-8"
                    })
                    .done(function () {
                        self.srvModel.customerEmail = self.emailAddressInput;
                    }).always(function () {
                        self.emailAddressFormSubmitting = false;
                    });
                } else {
                    this.emailAddressInputInvalid = true;
                }
            }
        }
    });
    </script>

@foreach (var paymentMethodHandler in PaymentMethodHandlerDictionary.Select(handler => handler.GetCheckoutUISettings()).Where(settings => settings != null))
{
    <partial name="@paymentMethodHandler.ExtensionPartial" model="@Model"/>
}
</body>
</html>
