<template>
  <div class="ma-3">
    <v-row align="center" justify="center">
      <v-img src="../assets/logo.svg"
             :max-width="logoWidth"
      />
    </v-row>

    <form novalidate @submit.prevent="performLogin">
      <v-row justify="center" v-if="unclaimed">
        <v-col
          cols="12" sm="8" md="6" lg="4" xl="2"
          class="text-body-1 mt-2"
        >
          <v-alert type="info"
                   icon="mdi-account-plus"
                   prominent
                   text
                   v-html="$t('login.unclaimed_html')"
          >
          </v-alert>
        </v-col>
      </v-row>

      <v-row justify="center">
        <v-col cols="12" sm="8" md="6" lg="4" xl="2">
          <v-text-field v-model="form.login"
                        :label="$t('common.email')"
                        :error-messages="getErrors('login')"
                        autocomplete="username"
                        autofocus
                        @blur="$v.form.login.$touch()"
          />
        </v-col>
      </v-row>

      <v-row justify="center">
        <v-col cols="12" sm="8" md="6" lg="4" xl="2">
          <v-text-field v-model="form.password"
                        :label="$t('common.password')"
                        :error-messages="getErrors('password')"
                        type="password"
                        autocomplete="current-password"
                        @input="$v.form.password.$touch()"
                        @blur="$v.form.password.$touch()"
          />
        </v-col>
      </v-row>

      <v-row justify="center">
        <v-col cols="12" sm="8" md="6" lg="4" xl="2">
          <v-btn color="primary"
                 type="submit"
                 :disabled="unclaimed"
          >{{ $t('login.login') }}
          </v-btn>
          <v-btn v-if="unclaimed"
                 class="mx-4"
                 color="primary"
                 @click="claim"
          >{{ $t('login.create_user_account') }}
          </v-btn>
        </v-col>
      </v-row>

      <v-row justify="center">
        <v-col cols="6" sm="4" md="3" lg="2" xl="1">
          <v-select v-model="locale"
                    :items="locales"
                    :label="$t('home.translation')"
                    prepend-icon="mdi-translate"
          >
          </v-select>
        </v-col>

        <v-col cols="6" sm="4" md="3" lg="2" xl="1">
          <v-select v-model="theme"
                    :items="themes"
                    :label="$t('home.theme')"
                    :prepend-icon="themeIcon"
          >
          </v-select>
        </v-col>
      </v-row>
    </form>

    <v-snackbar
      v-model="snackbar"
      bottom
      color="error"
    >
      {{ snackText }}
      <v-btn
        text
        @click="snackbar = false"
      >{{ $t('common.close') }}
      </v-btn>
    </v-snackbar>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import {email, required} from 'vuelidate/lib/validators'
import {Theme} from '@/types/themes'

export default Vue.extend({
  name: 'Login',
  data: function () {
    return {
      form: {
        login: '',
        password: '',
      },
      snackbar: false,
      snackText: '',
      unclaimed: false,
      locales: this.$i18n.availableLocales.map((x: any) => ({text: this.$i18n.t('common.locale_name', x), value: x})),
    }
  },
  validations: {
    form: {
      login: {required, email},
      password: {required},
    },
  },
  computed: {
    logoWidth(): number {
      let l = 100
      switch (this.$vuetify.breakpoint.name) {
        case 'xs':
          l = 100
        case 'sm':
        case 'md':
          l = 200
        case 'lg':
        case 'xl':
        default:
          l = 300
      }
      return l / (this.unclaimed ? 2 : 1)
    },

    locale: {
      get: function (): string {
        return this.$i18n.locale
      },
      set: function (locale: string): void {
        if (this.$i18n.availableLocales.includes(locale)) {
          this.$store.commit('setLocale', locale)
        }
      },
    },

    themes(): object[] {
      return [
        {text: this.$i18n.t(Theme.LIGHT), value: Theme.LIGHT},
        {text: this.$i18n.t(Theme.DARK), value: Theme.DARK},
        {text: this.$i18n.t(Theme.SYSTEM), value: Theme.SYSTEM},
      ]
    },
    themeIcon(): string {
      switch (this.theme) {
        case Theme.LIGHT:
          return 'mdi-brightness-7'
        case Theme.DARK:
          return 'mdi-brightness-3'
        case Theme.SYSTEM:
          return 'mdi-brightness-auto'
      }
      return ''
    },

    theme: {
      get: function (): Theme {
        return this.$store.state.persistedState.theme
      },
      set: function (theme: Theme): void {
        if (Object.values(Theme).includes(theme)) {
          this.$store.commit('setTheme', theme)
        }
      },
    },
  },
  mounted() {
    this.getClaimStatus()
  },
  methods: {
    getErrors(fieldName: string): string[] {
      const errors = [] as string[]

      const field = this.$v.form!![fieldName] as any
      if (field && field.$invalid && field.$dirty) {
        if (!field.required) errors.push(this.$t('common.required').toString())
        if (!field.email) errors.push(this.$t('dialog.add_user.field_email_error').toString())
      }
      return errors
    },
    async getClaimStatus() {
      this.unclaimed = !(await this.$komgaClaim.getClaimStatus()).isClaimed
    },
    async performLogin() {
      if (this.isUserValid()) {
        try {
          await this.$store.dispatch(
            'getMeWithAuth',
            {
              login: this.form.login,
              password: this.form.password,
            })

          await this.$store.dispatch('getLibraries')

          if (this.$route.query.redirect) {
            await this.$router.push({path: this.$route.query.redirect.toString()})
          } else {
            await this.$router.push({name: 'home'})
          }
        } catch (e) {
          this.showSnack(e?.message)
        }
      }
    },
    showSnack(message: string) {
      this.snackText = message
      this.snackbar = true
    },
    isUserValid(): boolean {
      this.$v.$touch()
      return !this.$v.$invalid
    },
    async claim() {
      if (this.isUserValid()) {
        try {
          await this.$komgaClaim.claimServer({
            email: this.form.login,
            password: this.form.password,
          } as ClaimAdmin)

          await this.performLogin()
        } catch (e) {
          this.showSnack(e.message)
        }
      }
    },
  },
})
</script>

<style scoped>

</style>
