<template>
  <v-container id="auth-login" theme="login" fluid fill-height class="auth-login wallpaper background-welcome pa-6" :style="wallpaper()">
    <v-theme-provider theme="login">
      <div class="auth-language">
        <v-select
          v-model="settings.ui.language"
          prepend-inner-icon="mdi-web"
          :items="options.Languages()"
          item-title="text"
          item-value="value"
          rounded="pill"
          density="compact"
          :menu-props="{ maxHeight: 346 }"
          flat
          hide-details
          variant="outlined"
          class="input-language"
          @update:model-value="onChangeLanguage"
        ></v-select>
      </div>
      <v-row id="auth-layout" class="auth-layout">
        <v-col cols="12" sm="9" md="6" lg="5" xl="3">
          <v-form ref="form" class="auth-login-form" accept-charset="UTF-8" @submit.prevent="onLogin">
            <v-card id="auth-login-box" class="elevation-12 auth-login-box pa-1 blur-7">
              <v-card-text>
                <p-auth-header></p-auth-header>
                <v-spacer></v-spacer>
                <v-row align="start" dense>
                  <template v-if="enterCode">
                    <v-col cols="12" class="text-body-2 text-center pb-1">
                      {{ $gettext(`Enter the code generated by your authenticator app:`) }}
                    </v-col>
                    <v-col cols="12" class="pb-0 d-flex justify-center">
                      <v-text-field
                        v-if="useRecoveryCode"
                        id="one-time-code"
                        ref="code"
                        v-model="code"
                        :disabled="loading"
                        :placeholder="$gettext('Recovery Code')"
                        :autofocus="enterCode && useRecoveryCode"
                        name="code"
                        variant="solo"
                        density="comfortable"
                        type="text"
                        inputmode="text"
                        hide-details
                        autocorrect="off"
                        autocapitalize="none"
                        autocomplete="none"
                        prepend-inner-icon="mdi-shield-check"
                        class="input-code text-selectable ma-4"
                        @keyup.enter="onLogin"
                      ></v-text-field>
                      <v-otp-input
                        v-else
                        ref="otp"
                        v-model="code"
                        :disabled="loading"
                        :length="6"
                        :max-width="320"
                        :label="$gettext('Verification Code')"
                        :autofocus="enterCode && !useRecoveryCode"
                        variant="solo-filled"
                        base-color="surface"
                        name="one-time-code"
                        type="number"
                        class="input-code"
                        @keyup.enter="onLogin"
                      >
                      </v-otp-input>
                    </v-col>
                  </template>
                  <template v-else>
                    <v-col cols="12" class="pb-1">
                      <v-text-field
                        id="auth-username"
                        v-model="username"
                        :disabled="loading || enterCode"
                        :placeholder="$gettext('Name')"
                        :autofocus="!enterCode"
                        name="username"
                        variant="solo"
                        density="comfortable"
                        type="text"
                        hide-details
                        autocorrect="off"
                        autocapitalize="none"
                        autocomplete="username"
                        class="input-username text-selectable"
                        prepend-inner-icon="mdi-account"
                        @keyup.enter="onLogin"
                      ></v-text-field>
                    </v-col>
                    <v-col cols="12" class="pb-1">
                      <v-text-field
                        id="auth-password"
                        v-model="password"
                        :disabled="loading"
                        :type="showPassword ? 'text' : 'password'"
                        :placeholder="$gettext('Password')"
                        name="password"
                        variant="solo"
                        density="comfortable"
                        hide-details
                        autocorrect="off"
                        autocapitalize="none"
                        autocomplete="current-password"
                        class="input-password text-selectable"
                        :append-inner-icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
                        prepend-inner-icon="mdi-lock"
                        @click:append-inner="showPassword = !showPassword"
                        @keyup.enter="onLogin"
                      ></v-text-field>
                    </v-col>
                  </template>
                  <v-col cols="12" class="auth-actions">
                    <div class="action-buttons auth-buttons pb-1 d-flex ga-3 align-center justify-center">
                      <v-btn
                        v-if="enterCode"
                        :block="$vuetify.display.xs"
                        color="highlight"
                        variant="outlined"
                        class="action-cancel opacity-80"
                        @click.stop.prevent="onCancel"
                      >
                        {{ $gettext(`Cancel`) }}
                      </v-btn>
                      <v-btn
                        v-else-if="registerUri"
                        :block="$vuetify.display.xs"
                        color="highlight"
                        variant="outlined"
                        class="action-register opacity-80"
                        @click.stop.prevent="onRegister"
                      >
                        {{ $gettext(`Create Account`) }}
                      </v-btn>
                      <v-btn
                        :disabled="loginDisabled"
                        :block="$vuetify.display.xs || !(registerUri || enterCode)"
                        color="highlight"
                        variant="flat"
                        class="action-confirm"
                        @click.stop.prevent="onLogin"
                      >
                        {{ $gettext(`Sign in`) }}
                        <v-icon :icon="$config.isRtl() ? 'mdi-chevron-left' : 'mdi-chevron-right'" end></v-icon>
                      </v-btn>
                    </div>
                    <div
                      v-if="enterCode"
                      class="auth-links text-center opacity-80"
                      :class="{ clickable: !useRecoveryCode }"
                      @click.stop.prevent="onUseRecoveryCode"
                    >
                      {{ $gettext(`Can't access your authenticator app or device?`) }}
                      {{ $gettext(`Use your recovery code or contact an administrator for help.`) }}
                    </div>
                    <div v-else-if="passwordResetUri" class="auth-links text-center opacity-80">
                      <a :href="passwordResetUri" class="text-secondary">
                        {{ $gettext(`Forgot password?`) }}
                      </a>
                    </div>
                  </v-col>
                  <template v-if="config.ext.oidc.enabled && !enterCode">
                    <v-col cols="12" class="oidc-actions">
                      <v-divider />
                      <div class="text-center oidc-buttons mt-6">
                        <v-btn :disabled="loading" color="highlight" variant="flat" block class="action-oidc-login" @click.stop.prevent="onOidcLogin">
                          <img alt="" class="oidc-icon v-icon--start mx-1" :src="config.ext.oidc.icon" />
                          {{ $gettext(`Continue with %{provider}`, { provider: config.ext.oidc.provider }) }}
                        </v-btn>
                      </div>
                    </v-col>
                  </template>
                </v-row>
              </v-card-text>
            </v-card>
          </v-form>
        </v-col>
      </v-row>
      <p-auth-footer></p-auth-footer>
    </v-theme-provider>
  </v-container>
</template>

<script>
import PAuthHeader from "component/auth/header.vue";
import PAuthFooter from "component/auth/footer.vue";
import Settings from "model/settings";
import * as options from "options/options";

export default {
  name: "PPageLogin",
  components: {
    PAuthHeader,
    PAuthFooter,
  },
  data() {
    return {
      loading: false,
      username: "",
      password: "",
      showPassword: false,
      useRecoveryCode: false,
      code: "",
      enterCode: false,
      sponsor: this.$config.isSponsor(),
      config: this.$config.values,
      siteDescription: this.$config.getSiteDescription(),
      wallpaperUri: this.$config.values.wallpaperUri,
      registerUri: this.$config.values.registerUri,
      passwordResetUri: this.$config.values.passwordResetUri,
      settings: new Settings(this.$config.getSettings()),
      options,
      rtl: this.$config.isRtl(),
    };
  },
  computed: {
    loginDisabled() {
      if (this.loading) {
        return true;
      } else if (this.enterCode) {
        const len = this.code.trim().length;
        return len !== 6 && len !== 12;
      }

      return this.username.trim() === "" || this.password.trim() === "";
    },
  },
  created() {
    const authError = window.localStorage.getItem("session.error");
    if (authError) {
      this.$notify.error(authError);
      window.localStorage.removeItem("session.error");
    }
  },
  mounted() {
    this.$view.enter(this, this.$refs?.form, 'input[value=""], button.action-confirm');
  },
  unmounted() {
    this.$view.leave(this);
  },
  methods: {
    wallpaper() {
      if (this.wallpaperUri) {
        return `background-image: url(${this.wallpaperUri});`;
      }

      return "";
    },
    load() {
      let homeRoute = this.$router.resolve({
        name: this.$session.getDefaultRoute(),
      });

      this.$session.followLoginRedirectUrl(homeRoute.href);
    },
    reset() {
      this.username = "";
      this.password = "";
      this.showPassword = false;
      this.useRecoveryCode = false;
      this.code = "";
      this.enterCode = false;
    },
    onChangeLanguage() {
      // Return if no language is set or the language has not been changed.
      if (!this.settings?.ui?.language || !this.settings.changed("ui", "language")) {
        return;
      }

      // Reload login page with locale query parameter to change UI language.
      const route = { name: "login", query: { locale: this.settings.ui.language } };
      window.window.location = this.$router.resolve(route).href;
    },
    onCancel() {
      if (this.loading) {
        return;
      }
      this.reset();
    },
    onRegister() {
      this.$view.redirect(this.registerUri);
    },
    onUseRecoveryCode() {
      if (!this.useRecoveryCode) {
        this.useRecoveryCode = true;
        this.$nextTick(() => {
          this.$view.focus(this.$refs?.code);
        });
      }
    },
    onLogin() {
      const username = this.username.trim();
      const password = this.password.trim();
      const code = this.code.trim();

      if (username === "" || password === "") {
        return;
      }

      this.loading = true;
      this.$session
        .login(username, password, code)
        .then(() => {
          this.load();
        })
        .catch((e) => {
          if (e.response?.data?.code === 32) {
            this.enterCode = true;
            this.$nextTick(() => {
              this.$view.focus(this.$refs?.otp);
            });
          }
          this.loading = false;
        });
    },
    onOidcLogin() {
      if (this.loading) {
        return;
      }

      if (this.config.ext?.oidc?.loginUri) {
        this.loading = true;
        this.$session.followRedirect(this.config.ext.oidc.loginUri);
      } else {
        this.$notify.warn(this.$gettext("Missing or invalid configuration"));
      }
    },
  },
};
</script>
