<template>
    <section v-if="logoutInProgress">
        <p class="text-center">
            <Spinner size="5rem" />
        </p>
        <div v-if="!impersonationActive">
            <iframe
                v-for="domain in universalDomains"
                :src="`${domain}/api/user/logout-universal`"
                style="width: 1px; height: 1px; opacity: .01"
            >
            </iframe>
        </div>
    </section>
    <section v-else>
        <div v-if="showTermsUpdate" class="alert alert-info container my-4 small">
            <h4 class="mb-3">
                <Icon v="info-circle" />
                <T>terms.update.header</T>
            </h4>
            <p>
                <T>terms.update.intro</T>
            </p>
            <ul>
                <li v-for="change in $t('terms.update.changes')">
                    <LinkedText :text="change" />
                </li>
            </ul>
            <p class="text-center">
                <button class="btn btn-primary" @click.prevent="dismissTermsUpdate">
                    <Icon v="shield-check" />
                    <T>confirm.ok</T>
                </button>
            </p>
        </div>

        <TabsNav
            :tabs="['general', 'cards', 'socials', 'circles', 'backup']"
            pills
            showheaders
            navclass="mb-3 border-bottom-0"
        >
            <template #general-header>
                <Icon v="user" />
                <T>user.headerLong</T>
            </template>
            <template #general>
                <div class="card mb-3">
                    <div class="card-body d-flex flex-column flex-md-row">
                        <div class="mx-2 text-center">
                            <p v-if="$isGranted('panel') || $isGranted('users') || $isGranted('community')">
                                <nuxt-link to="/admin" class="badge bg-primary text-white">
                                    <Icon v="collective-logo.svg" class="inverted" />
                                    <T>contact.team.member</T>
                                </nuxt-link>
                            </p>
                            <p class="mb-0">
                                <Avatar :user="$user()" validate />
                            </p>
                            <div>
                                <p class="mt-3 mb-1">
                                    <strong><T>user.avatar.change</T><T>quotation.colon</T></strong>
                                </p>
                                <div v-if="$user().avatarSource === 'gravatar'" class="mt-3">
                                    <a href="https://gravatar.com" target="_blank" rel="noopener" class="small">
                                        <Icon v="external-link" />
                                        Gravatar
                                    </a>
                                </div>
                                <div v-else class="mt-3">
                                    Gravatar:
                                    <a href="#" @click.prevent="setAvatar('gravatar')">
                                        <Avatar :user="$user()" :src="gravatar($user())" dsize="2rem" />
                                    </a>
                                </div>
                                <div v-if="$user().avatarSource">
                                    <a href="#" class="small" @click.prevent="setAvatar(null)">
                                        <Icon v="trash" />
                                        <T>crud.remove</T>
                                    </a>
                                </div>
                                <ImageUploader small sizes="avatar" @uploaded="uploaded" />
                                <p class="small my-2 avatar-social-hint">
                                    <T>user.avatar.social</T>
                                </p>
                            </div>
                        </div>
                        <div class="mx-2 flex-grow-1">
                            <Alert type="danger" :message="error" />

                            <div v-if="message" class="alert alert-success">
                                <p class="mb-0 narrow-message">
                                    <Icon :v="messageIcon" />
                                    <T :params="messageParams">{{ message }}</T>
                                </p>
                            </div>

                            <form :inert="savingUsername" @submit.prevent="changeUsername">
                                <h3 class="h6">
                                    <T>user.account.changeUsername.header</T>
                                </h3>
                                <input
                                    v-model="username"
                                    type="text"
                                    class="form-control mb-3"
                                    required
                                    minlength="4"
                                    maxlength="16"
                                >
                                <p v-if="usernameError" class="small text-danger">
                                    <Icon v="exclamation-triangle" />
                                    <span class="ml-1">{{ usernameError }}</span>
                                </p>
                                <div class="d-none d-md-block mt-3">
                                    <button class="btn btn-outline-primary" :disabled="username === user.username">
                                        <T>user.account.changeUsername.action</T>
                                    </button>
                                </div>
                                <div class="d-block-force d-md-none mt-3">
                                    <button class="btn btn-outline-primary w-100" :disabled="username === user.username">
                                        <T>user.account.changeUsername.action</T>
                                    </button>
                                </div>
                            </form>

                            <hr>

                            <form :inert="savingEmail" @submit.prevent="changeEmail">
                                <h3 class="h6">
                                    <T>user.account.changeEmail.header</T>
                                </h3>
                                <div v-if="!changeEmailAuthId" class="">
                                    <input v-model="email" type="email" class="form-control mb-3" required>
                                    <div class="d-flex flex-column flex-md-row">
                                        <Captcha v-if="showCaptcha" v-model="captchaToken" />
                                        <div :class="['d-none', 'd-md-block', showCaptcha ? 'ms-3' : '']">
                                            <button class="btn btn-outline-primary" :disabled="!canChangeEmail">
                                                <T>user.account.changeEmail.action</T>
                                            </button>
                                        </div>
                                        <div class="d-block-force d-md-none mt-3">
                                            <button class="btn btn-outline-primary w-100" :disabled="!canChangeEmail">
                                                <T>user.account.changeEmail.action</T>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                                <div v-else class="input-group mb-3">
                                    <input
                                        ref="code"
                                        v-model="code"
                                        type="text"
                                        class="form-control text-center"
                                        placeholder="000000"
                                        autofocus
                                        required
                                        minlength="0"
                                        maxlength="6"
                                        inputmode="numeric"
                                        pattern="[0-9]{6}"
                                        autocomplete="one-time-code"
                                    >
                                    <button class="btn btn-outline-primary">
                                        <Icon v="key" />
                                        <T>user.code.action</T>
                                    </button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>

                <AdPlaceholder :phkey="['content-0', 'content-mobile-0']" />

                <section class="mt-5">
                    <a href="#" class="btn btn-outline-danger" @click.prevent="logout">
                        <Icon v="sign-out" />
                        <T :params="{ username: $user().username }">user.logout</T>
                    </a>

                    <a
                        v-if="accounts && Object.keys(accounts).length > 1"
                        href="#"
                        class="btn btn-outline-danger"
                        @click.prevent="logoutAll"
                    >
                        <Icon v="sign-out" />
                        <T>user.logoutAll</T>
                    </a>

                    <a href="#" class="btn btn-outline-danger" @click.prevent="deleteAccount">
                        <Icon v="trash-alt" />
                        <T :params="{ username: $user().username }">user.deleteAccount</T>
                    </a>

                    <a v-if="impersonationActive" href="#" class="btn btn-outline-primary" @click.prevent="stopImpersonation">
                        <Icon v="user-secret" />
                        Stop impersonation
                    </a>
                </section>
            </template>

            <template #cards-header>
                <Icon v="id-card" />
                <T>profile.list</T>
            </template>
            <template #cards>
                <Loading :value="profiles">
                    <ul v-if="profiles !== undefined" class="list-group">
                        <li
                            v-for="locale in Object.keys($locales)"
                            :key="locale"
                            :class="['list-group-item', locale === $config.locale ? 'profile-current' : '']"
                        >
                            <ProfileOverview :username="username" :profile="profiles[locale]" :locale="locale" @update="setProfiles" />
                        </li>
                    </ul>
                </Loading>

                <AdPlaceholder :phkey="['content-1', 'content-mobile-1']" />
            </template>

            <template #socials-header>
                <Icon v="sign-in-alt" />
                <T>user.socialConnection.header</T>
            </template>
            <template #socials>
                <Loading :value="socialConnections">
                    <template #header>
                        <div class="form-check form-switch my-2">
                            <label>
                                <input v-model="socialLookup" class="form-check-input" type="checkbox">
                                <T>user.socialLookup</T>
                                <br>
                                <small><T>user.socialLookupWhy</T></small>
                            </label>
                        </div>
                    </template>
                    <ul v-if="socialConnections !== undefined" class="list-group">
                        <li v-for="(providerOptions, provider) in socialProviders" :key="provider" :class="['list-group-item', socialConnections[provider] !== undefined ? 'profile-current' : '']">
                            <SocialConnection
                                :provider="provider"
                                :provider-options="providerOptions"
                                :connection="socialConnections[provider]"
                                @disconnected="socialConnections[provider] = undefined"
                                @setAvatar="setAvatar"
                            />
                        </li>
                        <li :class="['list-group-item', $user().mfa ? 'profile-current' : '']">
                            <MfaConnection />
                        </li>
                    </ul>
                </Loading>
            </template>

            <template #circles-header>
                <Icon v="heart-circle" />
                <T>profile.circles.header</T>
            </template>
            <template #circles>
                <h5><T>profile.circles.yourMentions.header</T><T>quotation.colon</T></h5>
                <CircleMentions />
            </template>

            <template #backup-header>
                <Icon v="copy" />
                <T>profile.backup.headerShort</T>
            </template>
            <template #backup>
                <CardsBackup v-if="!$user().bannedReason" />
            </template>
        </TabsNav>

        <AdPlaceholder :phkey="['content-2', 'content-mobile-2']" />

        <div>
            <iframe
                v-for="domain in universalDomains"
                :src="`${domain}/api/user/init-universal/${$cookies.get('token')}`"
                style="width: 1px; height: 1px; opacity: .01"
            >
            </iframe>
        </div>
    </section>
</template>

<script>
import { longtimeCookieSetting } from '../src/cookieSettings.ts';
import { socialProviders } from '../src/socialProviders.ts';
import { gravatar } from '../src/helpers.ts';
import { mapState } from 'vuex';
import { usernameRegex } from '../src/username.ts';

export default {
    data() {
        return {
            username: this.$user().username,
            email: this.$user().email,

            message: '',
            messageParams: {},
            messageIcon: null,
            error: '',
            changeEmailAuthId: null,
            code: '',

            profiles: undefined,

            socialProviders,
            socialConnections: undefined,

            savingUsername: false,
            savingEmail: false,

            gravatar,

            showCaptcha: false,
            captchaToken: null,

            universalDomains: process.env.ALL_LOCALES_URLS.split(',').filter((x) => x !== process.env.BASE_URL),

            logoutInProgress: false,

            impersonationActive: !!this.$cookies.get('impersonator'),

            showTermsUpdate: new Date() < new Date(2023, 3, 6) &&
                    !this.$cookies.get('termsUpdateDismissed3'),

            socialLookup: this.$user().socialLookup,
        };
    },
    async mounted() {
        this.profiles = (await this.$axios.$get(`/profile/get/${this.$user().username}?version=2&props=hide`)).profiles;
        this.socialConnections = await this.$axios.$get('/user/social-connections');
        const user = await this.$axios.$get('/user/current');
        if (user) {
            this.$setToken(user.token);
        }

        const redirectTo = window.sessionStorage.getItem('after-login');
        if (this.$user() && redirectTo) {
            window.sessionStorage.removeItem('after-login');
            await this.$router.push(redirectTo);
        }
    },
    methods: {
        async changeUsername() {
            this.error = '';

            if (this.savingUsername) {
                return;
            }
            this.savingUsername = true;
            try {
                const response = await this.$post('/user/change-username', {
                    username: this.username,
                });

                if (response.error) {
                    this.error = response.error;
                    return;
                }

                this.$removeToken(this.$user().username);
                this.$setToken(response.token);
                this.username = this.$user().username;
                this.message = 'crud.saved';
                this.messageParams = {};
                this.messageIcon = 'check-circle';
                setTimeout(() => this.message = '', 3000);
            } finally {
                this.savingUsername = false;
            }
        },
        async changeEmail() {
            this.error = '';

            if (this.savingEmail) {
                return;
            }
            this.savingEmail = true;
            try {
                const response = await this.$post('/user/change-email', {
                    email: this.email,
                    authId: this.changeEmailAuthId,
                    code: this.code,
                    captchaToken: this.captchaToken,
                });

                if (response.error) {
                    this.error = response.error;
                    return;
                }

                if (!this.changeEmailAuthId) {
                    this.changeEmailAuthId = response.authId;
                    this.message = 'user.login.emailSent';
                    this.messageParams = { email: this.addBrackets(this.email) };
                    this.messageIcon = 'envelope-open-text';
                    this.$nextTick((_) => {
                        this.$refs.code.focus();
                    });
                } else {
                    this.changeEmailAuthId = null;
                    this.message = '';
                    this.messageParams = {};
                    this.code = null;

                    this.$setToken(response.token);
                    this.message = 'crud.saved';
                    this.messageParams = {};
                    this.messageIcon = 'check-circle';
                    setTimeout(() => this.message = '', 3000);
                }
            } finally {
                this.savingEmail = false;
            }
        },
        logout() {
            this.logoutInProgress = true;
            setTimeout(this.doLogout, 3000);
        },
        logoutAll() {
            window.localStorage.removeItem('account-tokens');
            this.logout();
        },
        doLogout() {
            this.$removeToken();
            this.logoutInProgress = false;
            setTimeout(() => window.location.reload(), 300);
        },
        setProfiles(profiles) {
            this.profiles = profiles;
        },
        async deleteAccount() {
            await this.$confirm(this.$t('user.deleteAccountConfirm'), 'danger');

            await this.$post('/user/delete');

            if (this.impersonationActive) {
                this.stopImpersonation();
            } else {
                this.logout();
            }
        },
        async setAvatar(source) {
            const response = await this.$post('/user/set-avatar', { source });

            this.$setToken(response.token);
        },
        async uploaded(ids) {
            await this.setAvatar(`${process.env.CLOUDFRONT}/images/${ids[0]}-avatar.png`);
        },
        async stopImpersonation() {
            this.$removeToken(this.$user().username);
            this.$cookies.set('token', this.$cookies.get('impersonator'), longtimeCookieSetting);
            this.$cookies.remove('impersonator');
            setTimeout(() => window.location.reload(), 300);
        },
        dismissTermsUpdate() {
            this.$cookies.set('termsUpdateDismissed3', true, longtimeCookieSetting);
            this.showTermsUpdate = false;
        },
        addBrackets(str) {
            return str ? `(${str})` : '';
        },
    },
    computed: {
        ...mapState([
            'user',
            'accounts',
        ]),
        canChangeEmail() {
            return this.email && this.captchaToken;
        },
        usernameError() {
            if (!this.username.match(usernameRegex)) {
                return this.$t('user.account.changeUsername.invalid');
            }
            if (this.username !== encodeURIComponent(this.username)) {
                return this.$t('user.account.changeUsername.nonascii', { encoded: encodeURIComponent(this.username) });
            }
            return null;
        },
    },
    watch: {
        email(v) {
            if (v !== this.$user().email) {
                this.showCaptcha = true;
            }
        },
        async socialLookup(v) {
            const response = await this.$post('/user/set-social-lookup', { socialLookup: v });

            this.$setToken(response.token);
        },
    },
};
</script>

<style lang="scss" scoped>
    @import "assets/variables";

    .profile-current {
        border-inline-start: 3px solid $primary;
    }

    .narrow-message {
        max-width: 56ch;
    }

    @include media-breakpoint-up('md') {
        .avatar-social-hint {
            max-width: 200px;
        }
    }
</style>
