<template>
    <Page v-if="profile">
        <section v-if="($isGranted('users') || $isGranted('community')) && user.bannedReason">
            <div class="alert alert-warning">
                <p class="h4">
                    <Icon v="ban" />
                    {{ $t('ban.banned') }}
                </p>
                <p>{{ user.bannedReason }}</p>
                <p class="mb-0 small">
                    <T>ban.appeal</T>
                </p>
            </div>
        </section>

        <AdPlaceholder :phkey="['header', null]" />

        <div class="position-relative">
            <div v-if="profile.sensitive.length && !contentWarningDismissed" class="content-warning text-center">
                <ContentWarning
                    :warnings="profile.sensitive"
                    @dismiss="contentWarningDismissed = true"
                />
            </div>
            <!--
            <MarkSus @hasSus="hasSus = true">
                <Profile :user="user" :profile="profile" :terms="terms" :expand-links="hasSus" />
            </MarkSus>
            -->

            <!--<ClientOnly>-->
            <Profile :user="user" :profile="profile" :terms="terms" />
            <!--<template #placeholder>
                    <div class="text-center" style="min-height: 400px">
                        <Spinner size="5rem" />
                    </div>
                </template>
            </ClientOnly>-->

            <div v-if="profile.sensitive.length && contentWarningDismissed" class="text-center">
                <ContentWarning
                    :warnings="profile.sensitive"
                    dismissed
                    class="small d-inline-block"
                    @blur="contentWarningDismissed = false"
                />
            </div>
        </div>

        <Separator icon="heart" />
        <section>
            <ShopifyEmbed />
        </section>

        <CardsBanner />

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

        <template #aside-left>
            <ProfileShare :user="user" class="d-none d-xxl-block" :main-pronoun="mainPronoun" />
            <AdPlaceholder :phkey="['aside-left', null]" class="d-none d-xxl-block" />
        </template>

        <template #aside-right>
            <div class="row">
                <div class="my-2 col-12 col-lg-4 col-xxl-12">
                    <div v-if="$user() && $user().username === user.username" class="list-group list-group-flare">
                        <div class="list-group-item pt-3">
                            <h5>
                                <Icon v="user" />
                                <T>profile.personal.header</T>
                            </h5>
                            <small><T>profile.personal.description</T></small>
                        </div>
                        <nuxt-link to="/editor" class="list-group-item list-group-item-action list-group-item-hoverable">
                            <Icon v="edit" />
                            <T>profile.edit</T>
                        </nuxt-link>
                        <template v-if="cardsEnabled">
                            <a v-if="!cardMenuVisible && !(profile.card === '' || profile.cardDark === '')" href="#" class="list-group-item list-group-item-action list-group-item-hoverable" @click.prevent="cardMenuVisible = true">
                                <Icon v="id-card" />
                                <T>profile.card.link</T>
                            </a>
                            <div v-else class="list-group-item">
                                <p class="small">
                                    <Icon v="id-card" />
                                    <T>profile.card.link</T><T>quotation.colon</T>
                                </p>
                                <small v-if="profile.card === '' || profile.cardDark === ''">
                                    <Spinner />
                                    <T>profile.card.generating</T>
                                </small>
                                <span v-else>
                                    <a
                                        v-if="profile.card"
                                        :href="profile.card"
                                        target="_blank"
                                        rel="noopener"
                                        class="btn btn-success btn-sm mx-1"
                                    >
                                        <Icon v="sun" />
                                        <T>mode.light</T>
                                    </a>
                                    <a
                                        v-if="profile.cardDark"
                                        :href="profile.cardDark"
                                        target="_blank"
                                        rel="noopener"
                                        class="btn btn-success btn-sm mx-1"
                                    >
                                        <Icon v="moon" />
                                        <T>mode.dark</T>
                                    </a>

                                    <hr v-if="profile.card || profile.cardDark">
                                    <small>
                                        <T>profile.card.generate</T><T>quotation.colon</T><br>
                                        <button class="btn btn-outline-success btn-sm" @click="generateCard(false)">
                                            <Icon v="sun" />
                                            <T>mode.light</T>
                                        </button>
                                        <button class="btn btn-outline-success btn-sm" @click="generateCard(true)">
                                            <Icon v="moon" />
                                            <T>mode.dark</T>
                                        </button>
                                    </small>
                                </span>
                            </div>
                        </template>
                        <template v-if="profile.events.length + profile.customEvents.length > 0">
                            <a
                                v-if="!icsMenuVisible"
                                href="#"
                                class="list-group-item list-group-item-action list-group-item-hoverable"
                                @click.prevent="icsMenuVisible = true"
                            >
                                <Icon v="calendar-plus" />
                                iCalendar
                            </a>
                            <div v-else class="list-group-item">
                                <p class="small">
                                    <Icon v="calendar-plus" />
                                    iCalendar
                                </p>
                                <CalendarIcs :url="icsLink" small />
                            </div>
                        </template>
                    </div>

                    <div v-if="$isGranted('*') || $isGranted('community')" class="list-group list-group-flare mt-3">
                        <div class="list-group-item pt-3">
                            <h5>
                                <Icon v="user-cog" />
                                <T>admin.header</T>
                            </h5>
                        </div>
                        <a
                            v-if="$isGranted('*')"
                            href="#"
                            class="list-group-item list-group-item-action list-group-item-hoverable small"
                            @click.prevent="impersonate()"
                        ><Icon v="user-secret" /> Impersonate
                        </a>
                        <nuxt-link
                            v-if="$isGranted('*')"
                            :to="`/admin/audit-log/${user.username}/${user.id}`"
                            class="list-group-item list-group-item-action list-group-item-hoverable small"
                        >
                            <Icon v="file-search" /> Audit log
                        </nuxt-link>
                        <div class="list-group-item pt-3">
                            <h6>
                                <Icon v="key" /> Authenticators
                            </h6>
                            <Loading :value="authenticators">
                                <p>
                                    <a v-if="!showExpiredAuthenticators" href="#" @click.prevent="showExpiredAuthenticators = true">
                                        Include expired ones
                                    </a>
                                </p>
                                <ul>
                                    <template v-for="authenticator in authenticators">
                                        <li
                                            v-if="showExpiredAuthenticators || authenticator.validUntil === null"
                                            :class="authenticator.validUntil === null ? '' : 'small text-muted'"
                                        >
                                            <Tooltip :text="authenticator.type">
                                                <Icon :v="authenticatorIcon(authenticator.type)" />
                                            </Tooltip>
                                            {{ $datetime($ulidTime(authenticator.id)) }}
                                            <pre><code>{{ authenticator.payload }}</code></pre>
                                        </li>
                                    </template>
                                </ul>
                            </Loading>
                        </div>
                    </div>
                </div>

                <AdPlaceholder :phkey="['aside-right', null]" class="d-block d-lg-none d-xxl-block" />

                <div class="my-2 col-12 col-lg-4 col-xxl-12">
                    <div v-if="Object.keys(user.profiles).length > 1" class="list-group list-group-flare">
                        <div class="list-group-item pt-3">
                            <h5>
                                <Icon v="language" />
                                <T>profile.language.header</T>
                            </h5>
                            <small><T :params="{ username: user.username }">profile.language.description</T><T>quotation.colon</T></small>
                        </div>
                        <LocaleLink
                            v-for="(options, locale) in $locales"
                            v-show="user.profiles[locale] !== undefined"
                            :key="locale"
                            :locale="locale"
                            :link="`/@${user.username}`"
                            :class="['list-group-item list-group-item-action list-group-item-hoverable small', locale === $config.locale ? 'list-group-item-active' : '']"
                        >
                            {{ options.name }}
                        </LocaleLink>
                    </div>
                </div>

                <div class="my-2 col-12 col-lg-4 col-xxl-12">
                    <ProfileShare :user="user" class="d-xxl-none" :main-pronoun="mainPronoun" />
                </div>
            </div>
        </template>

        <template #below>
            <Ban :user="user" :profile="profile" />
            <div class="text-center my-4 small">
                <AccessibilitySettings />
            </div>
        </template>
    </Page>
    <Page v-else-if="user.username">
        <div class="my-md-5 pt-md-2">
            <h2 class="text-nowrap mb-3">
                <Avatar :user="user" />
                @{{ username }}
            </h2>

            <div v-if="Object.values(allProfiles).length" class="list-group">
                <LocaleLink
                    v-for="(options, locale) in allProfiles"
                    :key="locale"
                    :locale="locale"
                    :link="`/@${username}`"
                    class="list-group-item list-group-item-action list-group-item-hoverable d-flex flex-column flex-md-row justify-content-between"
                >
                    <div class="h3">
                        {{ options.name }}
                    </div>
                    <div class="d-flex align-items-center">
                        <ForeignPronoun
                            v-for="pronoun in selectMainPronouns(user.profiles[locale])"
                            :key="pronoun"
                            :pronoun="pronoun"
                            :locale="locale"
                        />
                    </div>
                </LocaleLink>
            </div>
            <div v-else class="alert alert-info">
                <p class="mb-0">
                    <Icon v="info-circle" />
                    <T>profile.empty</T>
                </p>
            </div>

            <a v-for="link in verifiedLinks" :href="link" rel="me">&nbsp;</a>

            <Ban :user="user" />
        </div>

        <template #aside-right>
            <ProfileShare v-if="Object.keys(user.profiles).length" :user="user" show-qr-start class="aside-home" :main-pronoun="mainPronoun" />
        </template>
    </Page>
    <Page v-else>
        <NotFound />
    </Page>
</template>

<script>
import { longtimeCookieSetting } from '../src/cookieSettings.ts';
import { buildFlags } from '../src/flags.ts';
import { head, sleep } from '../src/helpers.ts';
import opinions from '../src/opinions.ts';
import mainPronoun from '../plugins/mainPronoun.ts';

export default mainPronoun.extend({
    async asyncData({ app, route }) {
        return {
            user: await app.$axios.$get(`/profile/get/${encodeURIComponent(route.params.pathMatch)}?version=2&props=pronouns,flags,opinions&lprops[${app.$config.locale}]=all`),
        };
    },
    data() {
        return {
            terms: [],
            cardCheckHandle: null,
            cardMenuVisible: false,
            icsMenuVisible: false,

            cardsEnabled: true,
            hasSus: false,

            contentWarningDismissed: false,

            authenticators: undefined,
            showExpiredAuthenticators: false,
        };
    },
    head() {
        const flags = buildFlags(this.$config.locale);
        return head({
            title: `@${this.username}`,
            description: this.profile ? this.profile.description : null,
            banner: `api/banner/@${this.username}.png`,
            noindex: true,
            keywords: this.profile
                ? this.profile.flags.map((flag) => this.$translateForPronoun(flags[flag].display, this.mainPronoun))
                : undefined,
        }, this.$translator);
    },
    computed: {
        profile() {
            for (const locale in this.user.profiles) {
                if (locale === this.$config.locale) {
                    return this.user.profiles[locale];
                }
            }

            return null;
        },
        allProfiles() {
            return Object.fromEntries(Object.entries(this.$locales).filter(([locale, _]) => {
                return this.user.profiles[locale] !== undefined;
            }));
        },
        username() {
            const base = this.$route.params.pathMatch;

            if (!this.profile) {
                return base;
            }

            if (this.user.username !== base && process.client) {
                history.pushState(
                    '',
                    document.title,
                    `/@${this.user.username}`,
                );
            }

            return this.user.username;
        },
        verifiedLinks() {
            return [...new Set(Object.values(this.user.profiles).map((p) => Object.keys(p.verifiedLinks || {}))
                .flat())];
        },
        icsLink() {
            return `${process.env.BASE_URL}/api/queer-calendar-${this.$config.locale}-@${this.username}.ics`;
        },
    },
    watch: {
        profile() {
            this.startCheckingForCard();
        },
    },
    async mounted() {
        if (this.$config.terminology.enabled) {
            if (this.$isSafari()) {
                await sleep(500); // spread out less important requests, it seems to cause issues on safari
            }
            this.terms = await this.$axios.$get('/terms');
        }
        if (this.$isGranted('*') || this.$isGranted('community')) {
            this.authenticators = await this.$axios.$get(`/admin/authenticators/${this.user.id}`);
        }
    },
    methods: {
        async generateCard(dark) {
            await this.$axios.$post(`/profile/request-card?dark=${dark ? '1' : '0'}`);
            this.profile[dark ? 'cardDark' : 'card'] = '';
            this.startCheckingForCard();
        },
        startCheckingForCard() {
            if (this.cardCheckHandle || !this.profile || this.profile.card || this.profile.cardDark) {
                return;
            }
            this.cardCheckHandle = setInterval(this.checkForCard, 3000);
        },
        async checkForCard() {
            try {
                const card = await this.$axios.$get('/profile/has-card');
                if (card.card !== '' && card.cardDark !== '') {
                    this.profile.card = card.card;
                    this.profile.cardDark = card.cardDark;
                    clearInterval(this.cardCheckHandle);
                }
            } catch {
                clearInterval(this.cardCheckHandle);
            }
        },
        selectMainPronouns(profile) {
            const best = [];
            for (const { value: pronoun, opinion } of profile.pronouns) {
                const opinionValue = opinions[opinion]?.value;
                if (opinionValue !== undefined) {
                    if (opinionValue >= 0) {
                        best.push(pronoun);
                    }
                } else {
                    const customOpinion = profile.opinions[opinion];
                    if (customOpinion !== undefined &&
                        customOpinion.colour !== 'grey' &&
                        customOpinion.style !== 'small' &&
                        !['ban', 'slash'].includes(customOpinion.icon) &&
                        !(customOpinion.icon || '').endsWith('-slash')
                    ) {
                        best.push(pronoun);
                    }
                }
            }

            return best.slice(0, 3);
        },
        async impersonate() {
            const { token } = await this.$axios.$get(`/admin/impersonate/${encodeURIComponent(this.username)}`);
            this.$cookies.set('impersonator', this.$cookies.get('token'), longtimeCookieSetting);
            this.$cookies.set('token', token, longtimeCookieSetting);
            await this.$router.push(`/${this.$config.user.route}`);
            setTimeout(() => window.location.reload(), 500);
        },
        authenticatorIcon(type) {
            switch (type) {
                case 'email':
                case 'changedEmail':
                    return 'envelope';
                case 'indieauth':
                    return 'indieauth.png';
                case 'mfa_secret':
                case 'mfa_recovery':
                    return 'mobile';
                default:
                    return `b:${type}`;
            }
        },
    },
});
</script>

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

    $aside-margin: 2 * $spacer;
    @include media-breakpoint-up('xxl') {
        aside {
            position: absolute;
            top: 0;
            left: calc(100% + #{$aside-margin});
            width: min(300px, calc((100vw - #{$container-width}) / 2 - #{$aside-margin}));
        }

        .aside-home {
            margin-top: 164px;
        }
    }

    .list-group-flare > :first-child {
        border-top: 3px solid $primary;
    }

    .content-warning {
        position: absolute;
        left: -2*$glassBlur;
        top: -2*$glassBlur;
        width: calc(100% + 4*#{$glassBlur});
        height: calc(100% + 4*#{$glassBlur});
        background: $gray-400;
        z-index: 30;
        .alert {
            margin: 3*$spacer auto;
            display: inline-block;
        }
    }
</style>
