<template>
    <div id="configure-two-factor">
        <div class="h-16 text-center" v-show="spinner">
            <span class="spinner spinner-xl text-primary-500"></span>
        </div>
        <div id="container-disable-two-factor" v-if="response.enabled" v-show="!spinner">
            <h2 class="font-medium text-neutral-900">{{ $t('dashboard.account.two_factor.disable.title') }}</h2>
            <div class="mt-6">
                <label class="input-label" for="grid-two-factor-token-disable">{{ $t('dashboard.account.two_factor.disable.field') }}</label>
                <input id="grid-two-factor-token-disable" type="number" class="input"
                       name="token"
                       v-model="token"
                       ref="token"
                       v-validate="'length:6'"
                       :class="{ error: errors.has('token') }"
                >
                <p class="input-help error" v-show="errors.has('token')">{{ errors.first('token') }}</p>
            </div>
            <div class="mt-6 w-full text-right">
                <button class="btn btn-sm btn-secondary mr-4" v-on:click="$emit('close')">
                    Cancel
                </button>
                <button class="btn btn-sm btn-red" type="submit"
                        :disabled="submitDisabled"
                        v-on:click.prevent="disableTwoFactor"
                >{{ $t('strings.disable') }}
                </button>
            </div>
        </div>
        <div id="container-enable-two-factor" v-else v-show="!spinner">
            <h2 class="font-medium text-neutral-900">{{ $t('dashboard.account.two_factor.setup.title') }}</h2>
            <div class="flex mt-6">
                <div class="flex-none w-full sm:w-1/2 text-center">
                    <div class="h-48">
                        <img :src="response.qr_image" id="grid-qr-code" alt="Two-factor qr image" class="h-48">
                    </div>
                    <div>
                        <p class="text-xs text-neutral-800 mb-2">{{ $t('dashboard.account.two_factor.setup.help') }}</p>
                        <p class="text-xs"><code class="clean">{{response.secret}}</code></p>
                    </div>
                </div>
                <div class="flex-none w-full sm:w-1/2">
                    <div>
                        <label class="input-label" for="grid-two-factor-token">{{ $t('dashboard.account.two_factor.setup.field') }}</label>
                        <input id="grid-two-factor-token" type="number" class="input"
                               name="token"
                               v-model="token"
                               ref="token"
                               v-validate="'length:6'"
                               :class="{ error: errors.has('token') }"
                        >
                        <p class="input-help error" v-show="errors.has('token')">{{ errors.first('token') }}</p>
                    </div>
                    <div class="mt-6">
                        <button class="btn btn-primary btn-jumbo" type="submit"
                                :disabled="submitDisabled"
                                v-on:click.prevent="enableTwoFactor"
                        >{{ $t('strings.enable') }}
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script lang="ts">
    import Vue from 'vue';
    import {isObject} from 'lodash';
    import {AxiosError, AxiosResponse} from "axios";

    export default Vue.extend({
        name: 'TwoFactorAuthentication',
        data: function () {
            return {
                spinner: true,
                token: '',
                submitDisabled: true,
                response: {
                    enabled: false,
                    qr_image: '',
                    secret: '',
                },
            };
        },

        /**
         * Before the component is mounted setup the event listener. This event is fired when a user
         * presses the 'Configure 2-Factor' button on their account page. Once this happens we fire off
         * a HTTP request to get their information.
         */
        mounted: function () {
            window.events.$on('two_factor:open', () => {
                this.prepareModalContent();
            });
        },

        watch: {
            token: function (value) {
                this.submitDisabled = value.length !== 6;
            },
        },

        methods: {
            /**
             * Determine the correct content to show in the modal.
             */
            prepareModalContent: function () {
                // Reset the data object when the modal is opened again.
                // @ts-ignore
                Object.assign(this.$data, this.$options.data());

                this.$flash.clear();
                window.axios.get(this.route('account.two_factor'))
                    .then((response: AxiosResponse) => {
                        this.response = response.data;
                        this.spinner = false;
                        Vue.nextTick().then(() => {
                            (this.$refs.token as HTMLElement).focus();
                        })
                    })
                    .catch((err: AxiosError) => {
                        if (!err.response) {
                            this.$flash.error(err.message);
                            console.error(err);
                            return;
                        }

                        const response = err.response;
                        if (response.data && isObject(response.data.errors)) {
                            response.data.errors.forEach((error: any) => {
                                this.$flash.error(error.detail);
                            });
                        }

                        this.$emit('close');
                    });
            },

            /**
             * Enable two-factor authentication on the account by validating the token provided by the user.
             * Close the modal once the request completes so that the success or error message can be shown
             * to the user.
             */
            enableTwoFactor: function () {
                return this._callInternalApi('account.two_factor.enable', 'enabled');
            },

            /**
             * Disables two-factor authentication for the client account and closes the modal.
             */
            disableTwoFactor: function () {
                return this._callInternalApi('account.two_factor.disable', 'disabled');
            },

            /**
             * Call the Panel API endpoint and handle errors.
             *
             * @private
             */
            _callInternalApi: function (route: string, langKey: string) {
                this.$flash.clear();
                this.spinner = true;

                window.axios.post(this.route(route), {token: this.token})
                    .then((response: AxiosResponse) => {
                        if (response.data.success) {
                            this.$flash.success(this.$t(`dashboard.account.two_factor.${langKey}`));
                        } else {
                            this.$flash.error(this.$t('dashboard.account.two_factor.invalid'));
                        }
                    })
                    .catch((error: AxiosError) => {
                        if (!error.response) {
                            this.$flash.error(error.message);
                            return;
                        }

                        const response = error.response;
                        if (response.data && isObject(response.data.errors)) {
                            response.data.errors.forEach((e: any) => {
                                this.$flash.error(e.detail);
                            });
                        }
                    })
                    .then(() => {
                        this.spinner = false;
                        this.$emit('close');
                    });
            }
        },
    })
</script>