<template>
  <div>
    <div v-if="!lcr">
      <v-row justify="center">
        <v-dialog v-model="tfaDialog" persistent max-width="600px">
          <v-card>
            <v-card-title>
              <span class="text-h5">{{ authTwoFactor }}</span>
            </v-card-title>
            <v-card-text>
              <v-text-field
                v-model="pin"
                :label="authEnterPin"
                required
                :error-messages="pinError"
                autofocus
                @keyup.enter="tfaVerify"
              ></v-text-field>
            </v-card-text>
            <v-card-actions>
              <v-btn color="blue darken-1" text @click="cancelTfaVerify()">{{
                cancel
              }}</v-btn>
              <v-spacer></v-spacer>
              <v-btn
                color="blue darken-1"
                :disabled="pin == null || pin.length == 0"
                text
                @click="tfaVerify()"
                >{{ authVerifyCode }}</v-btn
              >
            </v-card-actions>
          </v-card>
        </v-dialog>
      </v-row>
      <v-row align="center" justify="center" class="mx-auto mt-sm-12 mb-16">
        <v-col cols="12" offset-md="4">
          <form>
            <v-row>
              <!-- Customer logo -->
              <v-col v-if="showCustomSmallLogo()" cols="12">
                <div class="text-center">
                  <img :src="mediumLogoUrl" />
                </div>
              </v-col>

              <v-col v-if="showCustomMediumLogo()" cols="7">
                <div class="text-center">
                  <img :src="largeLogoUrl" />
                </div>
              </v-col>

              <v-col v-if="showCustomLargeLogo()" cols="7">
                <div class="text-center">
                  <img :src="largeLogoUrl" />
                </div>
              </v-col>

              <!-- Small AyaNova logo -->
              <v-col v-if="showSmallBrandLogo()" cols="12">
                <v-img
                  :src="require('../assets/logo.svg')"
                  contain
                  height="64"
                ></v-img>
              </v-col>
              <!-- Large AyaNova logo. -->
              <v-col v-if="showLargeBrandLogo()" cols="7" class="ml-16">
                <v-img
                  :src="require('../assets/logo.svg')"
                  contain
                  height="128"
                ></v-img>
              </v-col>
              <v-col v-if="formState.errorBoxMessage" cols="12" md="7">
                <gz-error
                  :error-box-message="formState.errorBoxMessage"
                ></gz-error>
              </v-col>
              <v-col v-if="showEvalUsers == true" cols="12" md="7">
                <v-select
                  v-model="selectedTrialUserId"
                  :items="selectLists.trialUsers"
                  item-text="name"
                  item-value="l"
                  label="Trial mode example users"
                  prepend-icon="$ayiQuestionCircle"
                  return-object
                  data-cy="selecttrialuser"
                  @click:prepend="trialHelpClick"
                  @input="trialUserSelected"
                >
                </v-select>
              </v-col>

              <v-col cols="12" md="7">
                <v-text-field
                  id="username"
                  v-model="input.username"
                  v-focus
                  name="username"
                  prepend-icon="$ayiUser"
                  autofocus
                  autocomplete="off"
                  autocorrect="off"
                  autocapitalize="off"
                  spellcheck="false"
                  :error="errorBadCreds"
                  @keyup.enter="onEnterUserName"
                ></v-text-field>
              </v-col>
              <v-col cols="12" md="7">
                <v-text-field
                  id="password"
                  v-model="input.password"
                  name="password"
                  :append-outer-icon="reveal ? '$ayiEye' : '$ayiEyeSlash'"
                  prepend-icon="$ayiKey"
                  :type="reveal ? 'text' : 'password'"
                  :error="errorBadCreds"
                  @keyup.enter="login"
                  @click:append-outer="reveal = !reveal"
                ></v-text-field>
              </v-col>
              <v-col cols="12" md="7" mt-1 mb-5>
                <v-btn
                  color="primary"
                  value="LOGIN"
                  :data-cy="`loginbutton${errorBadCreds ? '_failedcreds' : ''}`"
                  @click="login()"
                >
                  <v-icon>$ayiSignIn</v-icon>
                </v-btn>
              </v-col>
            </v-row>
          </form>
        </v-col>
      </v-row>
      <v-footer color="primary" padless absolute>
        <div
          v-if="showFooterLogo()"
          style="text-align: center;"
          class="mx-auto pa-4 mb-10 mb-sm-1 mt-n8"
        >
          <a
            href="https://ayanova.com"
            target="_blank"
            style="text-decoration:none"
            class="primary white--text text-caption"
          >
            <div v-if="showFooterLogo()" style="width: 100%;" class="mx-auto">
              <v-img
                style="margin: 0 auto;"
                :src="require('../assets/logo.svg')"
                width="48px"
                height="48px"
                max-height="48px"
                max-width="48px"
                contain
              ></v-img>
            </div>
            <div class="mx-auto">AyaNova {{ version }}</div>
            <div class="mx-auto">
              <span class="primary white--text text-caption">{{
                copyright
              }}</span>
            </div>
          </a>
        </div>
        <div
          v-else
          style="text-align: center;"
          class="mx-auto pa-4 mb-1 mb-sm-1"
        >
          <a
            href="https://ayanova.com"
            target="_blank"
            style="text-decoration:none"
            class="primary white--text text-caption"
          >
            <div class="mx-auto">AyaNova {{ version }}</div>
            <div class="mx-auto">
              <span class="primary white--text text-caption">{{
                copyright
              }}</span>
            </div>
          </a>
        </div>
      </v-footer>
    </div>
    <div v-else>
      <LICR :lcr="lcr" :pp="pp" @accepted="lcr = false"></LICR>
    </div>
  </div>
</template>
<script>
import { processLogin, processLogout } from "../api/authutil";
import ayaNovaVersion from "../api/ayanova-version";
import LICR from "../components/lcr-control.vue";
export default {
  components: {
    LICR
  },
  data() {
    return {
      input: {
        username: null,
        password: null
      },
      tfaDialog: false,
      authTwoFactor: null,
      authEnterPin: null,
      authVerifyCode: null,
      authPinInvalid: null,
      cancel: null,
      pin: null,
      tt: null,
      lcr: false,
      pp: false, //case 4205
      pinError: null,
      loggedInWithKnownPassword: false,
      hasSmallLogo: false,
      hasMediumLogo: false,
      hasLargeLogo: false,
      smallLogoUrl: null,
      mediumLogoUrl: null,
      largeLogoUrl: null,
      errorBadCreds: false,
      reveal: false,
      formState: { errorBoxMessage: null },
      showEvalUsers: false,
      selectedTrialUserId: 1,
      selectLists: {
        trialUsers: [
          {
            name: "SuperUser",
            l: "superuser",
            p: "l3tm3in"
          },
          {
            name: "Accounting",
            l: "Accounting",
            p: "Accounting"
          },
          {
            name: "Business admin",
            l: "BizAdmin",
            p: "BizAdmin"
          },
          {
            name: "Business admin - restricted",
            l: "BizAdminRestricted",
            p: "BizAdminRestricted"
          },
          {
            name: "Customer",
            l: "Customer",
            p: "Customer"
          },
          {
            name: "Customer - restricted",
            l: "CustomerRestricted",
            p: "CustomerRestricted"
          },
          {
            name: "Head office",
            l: "HeadOffice",
            p: "HeadOffice"
          },
          {
            name: "Inventory",
            l: "Inventory",
            p: "Inventory"
          },
          {
            name: "Inventory - restricted",
            l: "InventoryRestricted",
            p: "InventoryRestricted"
          },
          {
            name: "Sales",
            l: "Sales",
            p: "Sales"
          },
          {
            name: "Sales - restricted",
            l: "SalesRestricted",
            p: "SalesRestricted"
          },
          {
            name: "Service manager",
            l: "Service",
            p: "Service"
          },
          {
            name: "Service manager - restricted",
            l: "ServiceRestricted",
            p: "ServiceRestricted"
          },
          {
            name: "Service Technician",
            l: "Tech",
            p: "Tech"
          },
          {
            name: "Service Technician - restricted",
            l: "TechRestricted",
            p: "TechRestricted"
          },
          {
            name: "Subcontractor",
            l: "SubContractor",
            p: "SubContractor"
          },
          {
            name: "Subcontractor - restricted",
            l: "SubContractorRestricted",
            p: "SubContractorRestricted"
          },
          {
            name: "System Operations",
            l: "OpsAdmin",
            p: "OpsAdmin"
          },
          {
            name: "System Operations - restricted",
            l: "OpsAdminRestricted",
            p: "OpsAdminRestricted"
          },
          {
            name: "Translation - Deutsch / German",
            l: "de",
            p: "de"
          },
          {
            name: "Translation - Español / Spanish",
            l: "es",
            p: "es"
          },
          {
            name: "Translation - Français / French",
            l: "fr",
            p: "fr"
          }
        ]
      }
    };
  },
  computed: {
    copyright() {
      return ayaNovaVersion.copyright;
    },
    version() {
      return ayaNovaVersion.version;
    }
  },
  async created() {
    const vm = this;
    window.$gz.eventBus.$emit("menu-change", {
      isMain: true,
      icon: "",
      title: null
    });
    //reset password redirects here with preset creds
    //this will help the user identify it and hopefully remember it
    if (vm.$route.params.presetLogin) {
      vm.input.username = vm.$route.params.presetLogin;
      vm.input.password = vm.$route.params.presetPassword;
    }

    vm.smallLogoUrl = window.$gz.api.logoUrl("small");
    vm.mediumLogoUrl = window.$gz.api.logoUrl("medium");
    vm.largeLogoUrl = window.$gz.api.logoUrl("large");
    try {
      let res = await window.$gz.api.get("notify/hello");
      if (res.data != null) {
        //if the superuser exists with default credentials then use it to get them going unless the trial eval users exist in which case use bizadmin as the default
        //as it has more rights to view things
        if (res.data.eval == true) {
          vm.input.username = "BizAdmin";
          vm.input.password = "BizAdmin";
          vm.reveal = true; //might as well show it since it's the default anyway
        } else if (res.data.sudf == true) {
          //superuser is default creds
          vm.input.username = "superuser";
          vm.input.password = "l3tm3in";
          vm.reveal = true; //might as well show it since it's the default anyway
        }
        //However, if the eval users exist then
        vm.showEvalUsers = res.data.eval;
        vm.hasSmallLogo = res.data.sl;
        vm.hasMediumLogo = res.data.ml;
        vm.hasLargeLogo = res.data.ll;
        vm.lcr = res.data.lcr; //license consent required flag
        vm.pp = res.data.pp; //Perpetual build if true
      }

      //Live eval from website redirects here with generated creds set
      // ...login?usr={username}&pw={pw}
      //anything in window.location.search is placed in the 'search' route parameter by app.vue for parsing here because they are lost when the redirect happens to the login form as it's actually app.vue that gets hit first not login
      //Note that the $route.query system does not work no matter what I tried and seems to be broken in vue router so have to do it ourselves from the
      //Handle search query params
      if (vm.$route.params.search != undefined) {
        let params = new URLSearchParams(vm.$route.params.search);
        if (params.has("usr")) {
          vm.input.username = params.get("usr");
          vm.input.password = params.get("pw");
        }
      }
    } catch (error) {
      //squash it, this isn't critical
    }
  },
  methods: {
    async tfaVerify() {
      //
      //send 2fa code to server if ok, then proceed as normal
      const vm = this;
      if (vm.pin && vm.pin != "") {
        vm.pinError = null;

        try {
          const res = await window.$gz.api.upsert(
            "auth/tfa-authenticate",
            {
              pin: vm.pin,
              tempToken: vm.tt
            },
            true
          );

          if (res.error) {
            //don't expect this to ever get called but just in case
            // throw new Error(res.error);
            throw new Error(window.$gz.errorHandler.errorToString(res, vm));
          }
          await this.step2(res);
        } catch (error) {
          //bad PIN?
          if (
            error.message &&
            error.message.includes("ErrorUserNotAuthenticated")
          ) {
            vm.pinError = vm.authPinInvalid;
            return;
          }
          //server closed by server state setting?
          if (error.code == 2000 || error.code == 2001 || error.code == 2006) {
            vm.formState.errorBoxMessage = error.message;
            return;
          }
          //probably here because server unresponsive.
          if (error.message) {
            let msg = error.message;
            if (
              msg.includes("NetworkError") ||
              msg.includes("Failed to fetch")
            ) {
              msg =
                "Could not connect to AyaNova server at " +
                window.$gz.api.APIUrl("") +
                "\r\nError: " +
                error.message;
            }
            //this just makes the error a little cleaner to remove the extraneous typeerror
            msg = msg.replace(" TypeError:", "");
            vm.formState.errorBoxMessage = msg;
            return;
          }
        }
      }
    },
    cancelTfaVerify() {
      const vm = this;
      vm.tt = null;
      vm.pin = null;
      vm.errorBadCreds = false;
      vm.pinError = [];
      vm.input.username = null;
      vm.input.password = null;
      vm.tfaDialog = false;
    },
    showFooterLogo() {
      return (
        this.showCustomSmallLogo() ||
        this.showCustomMediumLogo() ||
        this.showCustomLargeLogo()
      );
    },
    showSmallBrandLogo() {
      return !this.hasMediumLogo && this.$vuetify.breakpoint.smAndDown;
    },
    showLargeBrandLogo() {
      if (this.showSmallBrandLogo()) {
        return false;
      }
      if (this.showCustomSmallLogo()) {
        return false;
      }
      if (this.showCustomMediumLogo()) {
        return false;
      }
      if (this.showCustomLargeLogo()) {
        return false;
      }
      return true;
    },
    showCustomSmallLogo() {
      return this.hasMediumLogo && this.$vuetify.breakpoint.smAndDown;
    },
    showCustomMediumLogo() {
      return this.hasMediumLogo && this.$vuetify.breakpoint.mdOnly;
    },
    showCustomLargeLogo() {
      return this.hasLargeLogo && this.$vuetify.breakpoint.lgAndUp;
    },
    trialUserSelected(item) {
      this.input.password = item.p;
      this.input.username = item.l;
    },
    trialHelpClick: function() {
      //open help nav for trial login
      window.$gz.eventBus.$emit("menu-click", {
        key: "app:help",
        data: "ay-evaluate#sample-users"
      });
    },
    onEnterUserName: function() {
      //move focus to password
      document.getElementsByName("password")[0].focus();
    },
    async login() {
      const vm = this;

      if (vm.input.username != "" && vm.input.password != "") {
        vm.errorBadCreds = false;
        vm.loggedInWithKnownPassword =
          vm.input.username == "superuser" && vm.input.password == "l3tm3in";

        try {
          const res = await window.$gz.api.upsert(
            "auth",
            {
              login: vm.input.username,
              password: vm.input.password
            },
            true
          );
          if (res.error) {
            throw new Error(window.$gz.errorHandler.errorToString(res, vm));
          }
          //check for 2fa enabled, if so then need to do one more step before process login can be called
          if (res.data.tfa) {
            this.authTwoFactor = res.data.authTwoFactor;
            this.authEnterPin = res.data.authEnterPin;
            this.authVerifyCode = res.data.authVerifyCode;
            this.authPinInvalid = res.data.authPinInvalid;
            this.tt = res.data.tt;
            this.cancel = res.data.cancel;
            this.pin = null;
            //prompt for 2fa
            this.tfaDialog = true;
            return;
          }

          await this.step2(res);
        } catch (error) {
          if (
            error.message &&
            error.message.includes("License agreement consent required")
          ) {
            window.location.reload();
          }
          //bad creds?
          if (
            error.message &&
            error.message.includes("ErrorUserNotAuthenticated")
          ) {
            vm.errorBadCreds = true;
            return;
          }
          //server closed by server state setting?
          if (error.code == 2000 || error.code == 2001 || error.code == 2006) {
            vm.formState.errorBoxMessage = error.message;
            return;
          }
          //probably here because server unresponsive.
          if (error.message) {
            let msg = error.message;

            if (
              msg.includes("NetworkError") ||
              msg.includes("Failed to fetch")
            ) {
              msg =
                "Could not connect to AyaNova server at " +
                window.$gz.api.APIUrl("") +
                "\r\nError: " +
                error.message;
            }
            //this just makes the error a little cleaner to remove the extraneous typeerror
            msg = msg.replace(" TypeError:", "");
            vm.formState.errorBoxMessage = msg;
            return;
          }
        }
      }
    },
    async step2(res) {
      const vm = this;
      await processLogin(res.data, vm.loggedInWithKnownPassword);
      //check if support and updates has expired and is paid for license and show warning if so
      //but not to customer logins, that's just shaming and will anger people
      if (
        !vm.$store.getters.isCustomerUser &&
        vm.$store.state.globalSettings.maintenanceExpired &&
        (vm.$store.state.globalSettings.licenseStatus == 3 ||
          vm.$store.state.globalSettings.licenseStatus == 4)
      ) {
        (async function() {
          await window.$gz.dialog.displayLTModalNotificationMessage(
            "MaintenanceExpiredNote",
            "MaintenanceExpired",
            "error",
            "https://ayanova.com/docs/adm-license/#maintenance-expired-message"
          );
        })();
      }

      //Show toast if out of date to non customer users, perpetual only ensured by server
      if (
        !vm.$store.getters.isCustomerUser &&
        !vm.$store.state.globalSettings.showUpdateAvailable
      ) {
        window.$gz.eventBus.$emit(
          "notify-warning",
          `AyaNova update available ${vm.$store.state.globalSettings.latestVersion}`,
          vm.$store.state.globalSettings.changeLogUrl,
          10000
        );
        // (async function() {
        //   await window.$gz.dialog.displayLTModalNotificationMessage(
        //     "MaintenanceExpiredNote",
        //     "MaintenanceExpired",
        //     "error",
        //     "https://ayanova.com/docs/adm-license/#maintenance-expired-message"
        //   );
        // })();
      }

      const toPath = vm.$route.params.topath; //set in app.vue::mounted
      if (toPath != undefined) {
        //open the url indicated
        vm.$router.push(vm.$route.params.topath);
      } else {
        vm.$router.push(vm.$store.state.homePage);
      }
    }
  },
  beforeRouteEnter(to, from, next) {
    //very important as this in conjunction with the menu options means
    //navigation guards work properly by just sending people here
    next(() => {
      processLogout();
      next();
    });
  }
};
</script>
