<template>
  <q-layout view="hHh lpR fFf">
    <img
      v-if="landspace"
      src="login/login_background.png"
      class="fit"
      style="position: fixed"
    />
    <q-page-container>
      <q-page
        class="row items-center"
        style="position: ; /*fixed*/"
        :class="landspace ? '' : 'justify-evenly'"
        :style="landspace ? { left: '50%' } : {}"
      >
        <q-card :style="{ width: (landspace ? 34 : 70) + 'vw' }">
          <q-card-section class="text-center text-h6">
            {{ $t("login") }}
          </q-card-section>
          <q-separator />
          <q-card-section class="fit">
            <q-form ref="login_form" @submit="onSubmit" @reset="onReset">
              <q-list class="fit">
                <q-item v-if="$store.state.advanced_debug">
                  <q-item-section>
                    <q-input
                      :autofocus="!data.ip_address"
                      outlined
                      :loading="data.loading"
                      :disable="data.loading"
                      v-model="data.ip_address"
                      :label="$t('server ip address')"
                      :hint="$t('please input server ip address')"
                      lazy-rules
                      :rules="[
                        (val) =>
                          (val && val.length > 0) ||
                          $t('Please type something'),
                        (val) =>
                          val == 'localhost' ||
                          /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
                            val
                          ) ||
                          $t('Please input vaild ip address'),
                      ]"
                      @keydown="
                        (evt) => {
                          if (evt.keyCode == 13) {
                            $refs?.user_name?.focus();
                          }
                        }
                      "
                    >
                      <template v-slot:prepend>
                        <q-icon name="img:login/network.png" />
                      </template>
                      <template v-if="data.ip_address" v-slot:append>
                        <q-icon
                          name="cancel"
                          @click.stop="data.ip_address = null"
                          class="cursor-pointer"
                        />
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>

                <q-item>
                  <q-item-section>
                    <q-input
                      :autofocus="!data.user_name"
                      outlined
                      ref="user_name"
                      :loading="data.loading"
                      :disable="data.loading"
                      v-model="data.user_name"
                      :label="$t('user name')"
                      :hint="$t('please input user name')"
                      lazy-rules
                      :rules="[
                        (val) =>
                          (val && val.length > 0) ||
                          $t('Please type something'),
                      ]"
                      @keydown="
                        (evt) => {
                          if (evt.keyCode == 13) {
                            $refs?.password_input?.focus();
                          }
                        }
                      "
                    >
                      <template v-slot:prepend>
                        <q-icon name="img:login/user.png" />
                      </template>
                      <template v-if="data.user_name" v-slot:append>
                        <q-icon
                          name="cancel"
                          @click.stop="data.user_name = null"
                          class="cursor-pointer"
                        />
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>

                <q-item>
                  <q-item-section>
                    <q-input
                      outlined
                      ref="password_input"
                      :loading="data.loading"
                      :disable="data.loading"
                      :type="data.show_password ? '' : 'password'"
                      v-model="data.password"
                      :label="$t('password')"
                      :hint="$t('please input password')"
                      lazy-rules
                      :rules="[
                        (val) =>
                          (val && val.length > 0) ||
                          $t('Please type something'),
                      ]"
                      @keydown="
                        (evt) => {
                          if (evt.keyCode == 13) {
                            $refs?.login_button?.click();
                          }
                        }
                      "
                    >
                      <template v-slot:prepend>
                        <q-icon name="img:login/password.png" />
                      </template>
                      <template v-if="data.password" v-slot:append>
                        <q-icon
                          :name="
                            data.show_password ? 'visibility' : 'visibility_off'
                          "
                          class="cursor-pointer"
                          @click="data.show_password = !data.show_password"
                        />
                        <q-icon
                          name="cancel"
                          @click.stop="data.password = null"
                          class="cursor-pointer"
                        />
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>
                <q-item class="q-mt-md">
                  <q-item-section>
                    <q-checkbox
                      :label="$t('remember password')"
                      v-model="remember_password"
                      :disable="data.loading"
                    />
                  </q-item-section>
                  <q-item-section>
                    <q-checkbox
                      :label="$t('auto login')"
                      v-model="auto_login"
                      @update:model-value="remember_password = true"
                      :disable="data.loading"
                    />
                  </q-item-section>
                </q-item>
              </q-list>
            </q-form>
          </q-card-section>
          <q-card-actions class="q-px-lg">
            <q-btn
              ref="login_button"
              class="full-width text-h6"
              :loading="data.loading"
              :label="$t('login')"
              no-caps
              style="
                background: #273de4;
                box-shadow: 0 4px 6px 0px rgb(39 60 228 / 40%);
              "
              text-color="white"
              @click="$refs?.login_form?.submit()"
            />
          </q-card-actions>
        </q-card>
      </q-page>
    </q-page-container>
  </q-layout>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, ref, Ref, computed } from "vue";

import GlobalData from "src/common/GlobalData";
import { Cookies, LocalStorage, SessionStorage, useQuasar } from "quasar";
import ClientConnection from "src/common/ClientConnection";
import PermissionLevel from "src/entities/PermissionLevel";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import { useStore } from "src/store";
import { Md5 } from "ts-md5/dist/md5";
import Initializer from "src/common/Initializer";
import { api } from "src/boot/axios";

class _Data {
  user_name: string | null = null;
  password: string | null = null;
  loading = false;
  ip_address = window.location.hostname;
  show_password = false;

  constructor() {
    let temp = LocalStorage.getItem("default_ip_address");
    if (temp) {
      this.ip_address = temp.toString();
    } else {
      this.ip_address = window.location.hostname;
    }

    temp = LocalStorage.getItem("default_user_name");
    if (temp) {
      this.user_name = temp.toString();
    }

    temp = LocalStorage.getItem("default_password");
    if (temp) {
      this.password = temp.toString();
    }
  }
}

export default defineComponent({
  name: "PageLogin",

  components: {},

  setup() {
    const $q = useQuasar();
    const $t = useI18n();
    const $route = useRouter();
    const $store = useStore();
    const data = reactive(new _Data());

    try {
      (window as any).setPcTheme();
    } catch {}

    const login_form: Ref<any> = ref(null);

    const remember_password = ref(false);
    const auto_login = ref(false);
    let cache_password: string | null = null;

    let web_socket: ClientConnection | null = null;
    let is_pwa = ["fullscreen", "standalone", "minimal-ui"].some(
      (displayMode) =>
        window.matchMedia("(display-mode: " + displayMode + ")").matches
    );

    const landspace = computed({
      get: () => $store.state.landspace,
      set: (val) => null,
    });

    EventBus.getInstance().on(EventNamesDefine.WindowResize, () => {
      landspace.value = window.innerHeight < window.innerWidth;
    });

    onMounted(() => {
      if (auto_login.value) {
        login_form.value.submit();
      }
    });

    try {
      remember_password.value = JSON.parse(
        Cookies.get("remember_password")
      ) as boolean;
      auto_login.value = JSON.parse(Cookies.get("auto_login")) as boolean;
      if (
        typeof remember_password.value == "undefined" ||
        remember_password.value == null
      ) {
        remember_password.value = false;
      }

      if (typeof auto_login.value == "undefined" || auto_login.value == null) {
        auto_login.value = false;
      }

      if (remember_password.value) {
        data.user_name = Cookies.get("user_name") ?? data.user_name;
        cache_password = Cookies.get("password");
        if (
          typeof cache_password != "undefined" &&
          cache_password != null &&
          cache_password.length == 32
        ) {
          data.password = cache_password;
        } else {
          cache_password = null;
        }
      }
    } catch {}

    return {
      login_form,
      data,
      remember_password,
      auto_login,
      landspace,
      is_pwa,
      async onSubmit() {
        data.loading = true;
        return new Promise((resolve) => {
          try {
            let global_data = GlobalData.getInstance();
            api
              .get("/get_websocket_port")
              .then((response) => {
                let final_ws_port = GlobalData.kDefaultWebsocektPort;
                if (response && typeof response.data != "undefined") {
                  if (typeof response.data != "number") {
                    const temp_port = parseInt(response.data);
                    if (!isNaN(temp_port) && temp_port != Infinity) {
                      final_ws_port = temp_port;
                    }
                  } else {
                    final_ws_port = response.data;
                  }
                  const url =
                    "ws://" +
                    data.ip_address +
                    ":" +
                    final_ws_port.toString() +
                    GlobalData.kWebsocketResource;
                  web_socket = new ClientConnection(
                    url,
                    data.user_name,
                    data.password == cache_password
                      ? data.password
                      : Md5.hashStr(data.password ?? "admin")
                  );
                  let timer = setTimeout(() => {
                    web_socket?.destory();
                    web_socket = null;
                    $q.notify({
                      color: "negative",
                      icon: "warning",
                      message:
                        $t.t("login fail!") +
                        $t.t("connect time out!") +
                        $t.t(
                          "please check server state, or check server ip address!"
                        ),
                      position: "center",
                      timeout: 1500,
                    });
                    SessionStorage.set("auth", PermissionLevel.None);
                    resolve(false);
                    data.loading = false;
                  }, 5000);
                  web_socket.login_callback = (is_login) => {
                    clearTimeout(timer);
                    if (is_login && web_socket) {
                      global_data.addClient(data.ip_address, web_socket);
                      global_data.setCurrentClientName(data.ip_address);

                      SessionStorage.set("auth", PermissionLevel.Root);
                      SessionStorage.set("url", url);
                      SessionStorage.set("name", data.ip_address);
                      SessionStorage.set("user_name", data.user_name);
                      SessionStorage.set(
                        "password",
                        data.password == cache_password
                          ? data.password
                          : Md5.hashStr(data.password ?? "admin")
                      );

                      // TODO add self to setConnects

                      if (remember_password.value) {
                        Cookies.set("remember_password", JSON.stringify(true), {
                          expires: 15,
                        });
                        Cookies.set(
                          "auto_login",
                          JSON.stringify(auto_login.value),
                          {
                            expires: 15,
                          }
                        );
                        Cookies.set("user_name", data.user_name ?? "admin", {
                          expires: 15,
                        });
                        Cookies.set(
                          "password",
                          data.password == cache_password
                            ? data.password ?? Md5.hashStr("admin")
                            : Md5.hashStr(data.password ?? "admin"),
                          {
                            expires: 15,
                          }
                        );
                      } else {
                        Cookies.remove("remember_password");
                        Cookies.remove("auto_login");
                        Cookies.remove("name");
                        Cookies.remove("user_name");
                        Cookies.remove("password");
                      }

                      $store.commit("setDeviceIpAddress", data.ip_address);

                      setTimeout(() => {
                        new Initializer({
                          $t,
                          $store,
                          $q,
                        })
                          .initialize()
                          .then(() => {
                            $store.commit("setInitialized");
                          });
                      }, 0);

                      $route.push("/");
                    } else {
                      $q.notify({
                        color: "negative",
                        icon: "warning",
                        message:
                          $t.t("login fail!") + $t.t("user or password error!"),
                        position: "center",
                        timeout: 1500,
                      });
                      SessionStorage.set("auth", PermissionLevel.None);
                    }
                    resolve(true);
                    data.loading = false;
                  };
                }
              })
              .catch(() => {
                resolve(true);
                data.loading = false;
              });
          } catch {
            resolve(true);
            data.loading = false;
          }
        });
      },
      onReset() {
        data.user_name = null;
        data.password = null;
        remember_password.value = false;
      },
    };
  },
});
</script>
