<template>
  <div class="login-page">
    <!-- User is already logged in -->
    <div v-if="isUserAlreadyLoggedIn" class="already-logged-in">
      <h2>{{ $t('login.already-logged-in-title') }}</h2>
      <p class="already-logged-in">
        {{ $t('login.already-logged-in-text') }}
        <span class="username">{{ existingUsername }}</span>
      </p>
      <Button class="login-button" :click="stayLoggedIn">
        {{ $t('login.proceed-to-dashboard') }}
      </Button>
      <Button class="login-button" :click="getOut">{{ $t('login.log-out-button') }}</Button>
      <span class="already-logged-in-note">
        You need to log out, in order to proceed as a different user.
      </span>
      <transition name="bounce">
        <p :class="`login-error-message ${status}`" v-show="message">{{ message }}</p>
      </transition>
    </div>
    <!-- Main login form -->
    <form class="login-form" v-if="(!isUserAlreadyLoggedIn) && isAuthenticationEnabled">
      <h2 class="login-title">{{ $t('login.title') }}</h2>
      <Input type="text"
        v-model="username"
        :onEnter="submitLogin"
        :label="$t('login.username-label')"
        class="login-field username"
      />
      <Input type="password"
        v-model="password"
        :onEnter="submitLogin"
        :label="$t('login.password-label')"
        class="login-field password"
      />
      <label>{{ $t('login.remember-me-label') }}</label>
      <v-select
        v-model="timeout"
        :selectOnTab="true"
        :options="dropDownMenu"
        :map-keydown="(map) => ({ ...map, 13: () => submitLogin() })"
        class="login-time-dropdown"
      />
      <Button class="login-button" :click="submitLogin">
        {{ $t('login.login-button') }}
      </Button>
      <transition name="bounce">
        <p :class="`login-error-message ${status}`" v-show="message">{{ message }}</p>
      </transition>
    </form>
    <!-- Guest login form -->
    <form class="guest-form"
      v-if="isGuestAccessEnabled && !isUserAlreadyLoggedIn && isAuthenticationEnabled">
      <h2 class="login-title">{{ $t('login.guest-label') }}</h2>
      <Button class="login-button" :click="guestLogin">
        {{ $t('login.proceed-guest-button') }}
      </Button>
      <p class="guest-intro">
        {{ $t('login.guest-intro-1') }}<br>
        {{ $t('login.guest-intro-2') }}
      </p>
    </form>
    <!-- Edge case - guest mode enabled, but no users configured -->
    <div class="not-configured" v-if="!isAuthenticationEnabled">
      <h2>{{ $t('login.error') }}</h2>
      <p>{{ $t('login.error-no-user-configured') }}</p>
      <Button class="login-button" :click="guestLogin">
        {{ $t('login.error-go-home-button') }}
      </Button>
    </div>
  </div>
</template>

<script>
import router from '@/router';
import Button from '@/components/FormElements/Button';
import Input from '@/components/FormElements/Input';
import Keys from '@/utils/StoreMutations';
import { localStorageKeys } from '@/utils/config/defaults';
import { InfoHandler, WarningInfoHandler, InfoKeys } from '@/utils/logging/ErrorHandler';
import {
  checkCredentials,
  login,
  isLoggedIn,
  logout,
  isGuestAccessEnabled,
  getLogoutRedirectUrl,
} from '@/utils/auth/Auth';

export default {
  name: 'login',
  components: {
    Button,
    Input,
  },
  data() {
    return {
      username: '',
      password: '',
      message: '',
      status: 'waiting', // wating, error, success
      timeout: undefined,
    };
  },
  computed: {
    appConfig() {
      return this.$store.getters.appConfig;
    },
    /* Data for timeout dropdown menu, translated label + value in ms */
    dropDownMenu() {
      return [
        { label: this.$t('login.remember-me-never'), time: 0 },
        { label: this.$t('login.remember-me-hour'), time: 14400 * 1000 },
        { label: this.$t('login.remember-me-day'), time: 86400 * 1000 },
        { label: this.$t('login.remember-me-week'), time: 604800 * 1000 },
        { label: this.$t('login.remember-me-long-time'), time: 604800 * 52 * 1000 },
      ];
    },
    /* Translations for login response messages */
    responseMessages() {
      return {
        missingUsername: this.$t('login.error-missing-username'),
        missingPassword: this.$t('login.error-missing-password'),
        incorrectUsername: this.$t('login.error-incorrect-username'),
        incorrectPassword: this.$t('login.error-incorrect-password'),
        successMsg: this.$t('login.success-message'),
      };
    },
    existingUsername() {
      return localStorage[localStorageKeys.USERNAME];
    },
    users() {
      const auth = this.appConfig.auth || {};
      return Array.isArray(auth) ? auth : auth.users || [];
    },
    isUserAlreadyLoggedIn() {
      const loggedIn = (!this.users || this.users.length === 0 || isLoggedIn());
      return (loggedIn && this.existingUsername);
    },
    isGuestAccessEnabled() {
      return isGuestAccessEnabled();
    },
    isAuthenticationEnabled() {
      return (this.appConfig && this.appConfig.auth && this.users.length > 0);
    },
  },
  methods: {
    /* Checks form is filled in, then initiates the login, and redirects to /home */
    submitLogin() {
      // Use selected timeout, if available,else revedrt to zero
      const timeout = this.timeout ? this.timeout.time : 0;
      // Check users credentials
      const response = checkCredentials(
        this.username,
        this.password,
        this.users, // All users
        this.responseMessages, // Translated response messages
      );
      this.message = response.msg; // Show error or success message to the user
      this.status = response.correct ? 'success' : 'error';
      if (response.correct) { // Yay, credentials were correct :)
        login(this.username, this.password, timeout); // Login, to set the cookie
        this.$store.commit(Keys.AUTH_CHANGED); // Trigger reactive auth-dependent getters
        this.goHome();
        InfoHandler(`Succesfully signed in as ${this.username}`, InfoKeys.AUTH);
      } else {
        WarningInfoHandler('Unable to Sign In', InfoKeys.AUTH, this.message);
      }
    },
    /* Calls function to double-check guest access enabled, then log in as guest */
    guestLogin() {
      const isAllowed = this.isGuestAccessEnabled;
      if (isAllowed) {
        this.$toast.success(this.$t('login.logged-in-guest'));
        InfoHandler('Logged in as Guest', InfoKeys.AUTH);
        this.goHome();
      } else {
        this.$toast.error(this.$t('login.error-guest-access'));
        WarningInfoHandler('Guest Access Not Allowed', InfoKeys.AUTH);
      }
    },
    /* Calls logout, shows status message, and refreshed page */
    getOut() {
      logout();
      this.status = 'success';
      this.message = 'Logging out...';
      const redirectUrl = getLogoutRedirectUrl();
      if (redirectUrl) {
        setTimeout(() => { window.location.href = redirectUrl; }, 250);
      } else {
        this.refreshPage();
      }
    },
    /* Logged in user redirects to home page */
    stayLoggedIn() {
      this.status = 'success';
      this.message = 'Redirecting...';
      this.goHome();
    },
    /* Refreshes the page */
    refreshPage() {
      setTimeout(() => { location.reload(); }, 250);  
    },
    /* Redirects to the homepage */
    goHome() {
      setTimeout(() => { // Wait a short while, then redirect back home
        router.push({ path: '/' });
      }, 250);
    },
  },
  created() {
    setTimeout(() => { this.timeout = this.dropDownMenu[0]; }, 1);  
  },
};

</script>

<style lang="scss">

/* Login page base styles */
.login-page {
  display: flex;
  align-items: center;
  justify-content: center;
  justify-content: space-evenly;
  min-height: calc(100vh - var(--footer-height));

  /* User is already logged in note */
  div.already-logged-in {
    margin: 0 auto 0.5rem;
    p.already-logged-in {
      margin: 0 auto 0.5rem;
      text-align: center;
    }
    span.username {
      font-weight: bold;
      text-transform: capitalize;
    }
    span.already-logged-in-note {
      font-size: 0.8rem;
      opacity: var(--dimming-factor);
      text-align: left;
    }
  }

  /* Login form container */
  form.login-form, form.guest-form, div.already-logged-in, div.not-configured {
    background: var(--login-form-background);
    color: var(--login-form-color);
    border: 1px solid var(--login-form-color);
    border-radius: var(--curve-factor);
    font-size: 1.4rem;
    padding: 2rem;
    margin: 2rem;
    max-width: 22rem;
    display: flex;
    flex-direction: column;

    /* Login form title */
    h2 {
      font-size: 2rem;
      margin: 0 0 1rem 0;
      text-align: center;
      cursor: default;
    }

    /* Set sizings for input fields and login button */
    .login-field input, Button.login-button {
      width: 20rem;
      margin: 0.5rem auto;
      font-size: 1.4rem;
      padding: 0.5rem 1rem;
    }

    /* Custom colors for username/ password input fields */
    .login-field input {
      color: var(--login-form-color);
      border-color: var(--login-form-color);
      background: var(--login-form-background);
    }
    /* Custom colors for Login Button */
    Button.login-button {
      background: var(--login-form-color);
      border-color: var(--login-form-background);
      color: var(--login-form-background);
      &:hover {
        color: var(--login-form-color);
        border-color: var(--login-form-color);
        background: var(--login-form-background);
      }
      &:active, &:focus {
        box-shadow: 1px 1px 6px var(--login-form-color);
      }
    }
    /* Apply color to status message, depending on status */
    p.login-error-message {
      font-size: 1rem;
      text-align: center;
      &.waiting { color: var(--login-form-color); }
      &.success { color: var(--success); }
      &.error { color: var(--warning); }
    }
    p.guest-intro {
      font-size: 0.8rem;
      opacity: var(--dimming-factor);
      text-align: left;
    }
  }
}

/* Enter animations for error/ success message */
.bounce-enter-active { animation: bounce-in 0.25s; }
.bounce-leave-active { animation: bounce-in 0.25s reverse; }
@keyframes bounce-in {
  0% { transform: scale(0); }
  50% { transform: scale(1.25); }
  100% { transform: scale(1); }
}

/* Custom styles for dropdown component */
.v-select.login-time-dropdown {
  margin: 0.5rem 0;
  .vs__dropdown-toggle {
    border-color: var(--login-form-color);
    background: var(--login-form-background);
    cursor: pointer;
    span.vs__selected {
      color: var(--login-form-color);
    }
    .vs__actions svg path { fill: var(--login-form-color); }
  }
  ul.vs__dropdown-menu {
    background: var(--login-form-background);
    border-color: var(--login-form-color);
    li {
      color: var(--login-form-color);
      &:hover {
        color: var(--login-form-background);
        background: var(--login-form-color);
      }
      &.vs__dropdown-option--highlight {
        color: var(--login-form-background) !important;
        background: var(--login-form-color);
      }
    }
  }
}
</style>
