import {
    Component,
    Input,
    OnInit,
} from '@angular/core';

import { PaymentMethodType } from 'jslib/enums/paymentMethodType';

import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';

const Keys = {
    stripeTest: 'pk_test_KPoCfZXu7mznb9uSCPZ2JpTD',
    stripeLive: 'pk_live_bpN0P37nMxrMQkcaHXtAybJk',
    btSandbox: 'sandbox_r72q8jq6_9pnxkwm75f87sdc2',
    btProduction: 'production_qfbsv8kc_njj2zjtyngtjmbjd',
};

const StripeElementStyle = {
    base: {
        color: '#333333',
        fontFamily: '"Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, ' +
            '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
        fontSize: '14px',
        fontSmoothing: 'antialiased',
    },
    invalid: {
        color: '#333333',
    },
};

const StripeElementClasses = {
    focus: 'is-focused',
    empty: 'is-empty',
    invalid: 'is-invalid',
};

@Component({
    selector: 'app-payment',
    templateUrl: 'payment.component.html',
})
export class PaymentComponent implements OnInit {
    @Input() showOptions = true;
    @Input() method: 'card' | 'paypal' | 'bank' = 'card';
    @Input() hideBank = false;
    @Input() hidePaypal = false;

    bank: any = {
        routing_number: null,
        account_number: null,
        account_holder_name: null,
        account_holder_type: '',
        currency: 'USD',
        country: 'US',
    };

    private btScript: HTMLScriptElement;
    private btInstance: any = null;
    private stripeScript: HTMLScriptElement;
    private stripe: any = null;
    private stripeElements: any = null;
    private stripeCardNumberElement: any = null;
    private stripeCardExpiryElement: any = null;
    private stripeCardCvcElement: any = null;

    constructor(private platformUtilsService: PlatformUtilsService) {
        this.stripeScript = window.document.createElement('script');
        this.stripeScript.src = 'https://js.stripe.com/v3/';
        this.stripeScript.async = true;
        this.stripeScript.onload = () => {
            this.stripe = (window as any).Stripe(
                this.platformUtilsService.isDev() ? Keys.stripeTest : Keys.stripeLive);
            this.stripeElements = this.stripe.elements();
            this.setStripeElement();
        };
        this.btScript = window.document.createElement('script');
        this.btScript.src = 'scripts/dropin.js';
        this.btScript.async = true;
    }

    ngOnInit() {
        if (!this.showOptions) {
            this.hidePaypal = this.method !== 'paypal';
            this.hideBank = this.method !== 'bank';
        }
        window.document.head.appendChild(this.stripeScript);
        if (!this.hidePaypal) {
            window.document.head.appendChild(this.btScript);
        }
    }

    ngOnDestroy() {
        window.document.head.removeChild(this.stripeScript);
        window.setTimeout(() => {
            Array.from(window.document.querySelectorAll('iframe')).forEach((el) => {
                if (el.src != null && el.src.indexOf('stripe') > -1) {
                    try {
                        window.document.body.removeChild(el);
                    } catch { }
                }
            });
        }, 200);
        if (!this.hidePaypal) {
            window.document.head.removeChild(this.btScript);
            window.setTimeout(() => {
                Array.from(window.document.head.querySelectorAll('script')).forEach((el) => {
                    if (el.src != null && el.src.indexOf('paypal') > -1) {
                        try {
                            window.document.head.removeChild(el);
                        } catch { }
                    }
                });
                const btStylesheet = window.document.head.querySelector('#braintree-dropin-stylesheet');
                if (btStylesheet != null) {
                    try {
                        window.document.head.removeChild(btStylesheet);
                    } catch { }
                }
            }, 200);
        }
    }

    changeMethod() {
        this.btInstance = null;

        if (this.method === 'paypal') {
            window.setTimeout(() => {
                (window as any).braintree.dropin.create({
                    authorization: this.platformUtilsService.isDev() ? Keys.btSandbox : Keys.btProduction,
                    container: '#bt-dropin-container',
                    paymentOptionPriority: ['paypal'],
                    paypal: {
                        flow: 'vault',
                        buttonStyle: {
                            label: 'pay',
                            size: 'medium',
                            shape: 'pill',
                            color: 'blue',
                        },
                    },
                }, (createErr: any, instance: any) => {
                    if (createErr != null) {
                        // tslint:disable-next-line
                        console.error(createErr);
                        return;
                    }
                    this.btInstance = instance;
                });
            }, 250);
        } else {
            this.setStripeElement();
        }
    }

    createPaymentToken(): Promise<[string, PaymentMethodType]> {
        return new Promise((resolve, reject) => {
            if (this.method === 'paypal') {
                this.btInstance.requestPaymentMethod().then((payload: any) => {
                    resolve([payload.nonce, PaymentMethodType.PayPal]);
                }).catch((err: any) => {
                    reject(err.message);
                });
            } else if (this.method === 'card' || this.method === 'bank') {
                let type = PaymentMethodType.Card;
                let sourceObj: any = null;
                let createObj: any = null;
                if (this.method === 'card') {
                    sourceObj = this.stripeCardNumberElement;
                } else {
                    type = PaymentMethodType.BankAccount;
                    sourceObj = 'bank_account';
                    createObj = this.bank;
                }
                this.stripe.createToken(sourceObj, createObj).then((result: any) => {
                    if (result.error) {
                        reject(result.error.message);
                    } else if (result.token && result.token.id != null) {
                        resolve([result.token.id, type]);
                    } else {
                        reject();
                    }
                });
            }
        });
    }

    private setStripeElement() {
        window.setTimeout(() => {
            if (this.method === 'card') {
                if (this.stripeCardNumberElement == null) {
                    this.stripeCardNumberElement = this.stripeElements.create('cardNumber', {
                        style: StripeElementStyle,
                        classes: StripeElementClasses,
                        placeholder: '',
                    });
                }
                if (this.stripeCardExpiryElement == null) {
                    this.stripeCardExpiryElement = this.stripeElements.create('cardExpiry', {
                        style: StripeElementStyle,
                        classes: StripeElementClasses,
                    });
                }
                if (this.stripeCardCvcElement == null) {
                    this.stripeCardCvcElement = this.stripeElements.create('cardCvc', {
                        style: StripeElementStyle,
                        classes: StripeElementClasses,
                        placeholder: '',
                    });
                }
                this.stripeCardNumberElement.mount('#stripe-card-number-element');
                this.stripeCardExpiryElement.mount('#stripe-card-expiry-element');
                this.stripeCardCvcElement.mount('#stripe-card-cvc-element');
            }
        }, 50);
    }
}
