<template>
  <div class="pa-4 getlink-root fill-height">
    <div v-if="!loggedIn" class="text-center">
      <v-icon class="getlink-image">$vuetify.icons.getlink</v-icon>
      <div class="getlink-title">{{ $t("getlink.title") }}</div>
      <div class="getlink-info">{{ $t("getlink.info") }}</div>
      <div color="rgba(255,255,255,0.1)" class="text-center">
        <v-form v-model="isValid" ref="form">
          <v-text-field v-model="user.user_id" :label="$t('getlink.username')" color="black" background-color="white" solo
            :rules="[(v) => !!v || $t('login.username_required')]" :error="userErrorMessage != null"
            :error-messages="userErrorMessage" required v-on:keyup.enter="onUsernameEnter" v-on:keydown="hasError = false"></v-text-field>

          <!-- <div class="error--text" v-if="loadingLoginFlows">Loading login flows...</div> -->

          <div class="error--text" v-if="hasError">{{ this.message }}</div>

          <interactive-auth ref="interactiveAuth" />

          <v-btn id="btn-login" :disabled="!isValid || loading" color="primary" depressed block @click.stop="handleLogin"
            :loading="loading" class="filled-button mt-4">{{ $t("getlink.next") }}</v-btn>
          <v-btn color="black" depressed text block @click.stop="goToLoginPage" class="text-button">{{ $t("menu.login")
          }}</v-btn>
        </v-form>
      </div>
    </div>
    <div v-else style="position:relative" class="getlink-loggedin">
      <!-- Logged in/account created -->
      <div class="getlink-title">{{ $t("getlink.hello", { user: $matrix.currentUserDisplayName }) }}</div>
      <div class="getlink-subtitle">{{ $t("getlink.ready_to_share") }}</div>
      <copy-link ref="qr" :locationLink="directMessageLink" i18nQrPopupTitleKey="getlink.scan_title"
        v-on:long-tap="copyQRImage">
        <template v-slot:share>
          <div v-if="shareSupported" class="clickable getlink-share" @click="shareLink">
            <div>{{ $t("getlink.share_qr") }}</div>
            <v-img src="@/assets/icons/ic_share.svg" />
          </div>
        </template>
      </copy-link>
      <div class="getlink-buttons">
        <v-btn color="black" depressed @click.stop="goHome" class="outlined-button">{{ $t("getlink.continue") }}</v-btn>
        <v-btn color="black" depressed text block @click.stop="getDifferentLink" class="text-button">{{
          $t("getlink.different_link") }}</v-btn>
      </div>
    </div>
    <div :class="{ 'toast-at-bottom': true, 'visible': showQRCopiedToast }">{{ $t("getlink.qr_image_copied") }}</div>
  </div>
</template>

<script>
import User from "../models/user";
import rememberMeMixin from "./rememberMeMixin";
import * as sdk from "matrix-js-sdk";
import logoMixin from "./logoMixin";
import InteractiveAuth from './InteractiveAuth.vue';
import CopyLink from "./CopyLink.vue"
import util from "../plugins/utils";

export default {
  name: "GetLink",
  mixins: [rememberMeMixin, logoMixin],
  components: { InteractiveAuth, CopyLink },
  data() {
    return this.defaultData();
  },
  computed: {
    loggedIn() {
      return this.$store.state.auth.status.loggedIn;
    },
    currentUser() {
      return this.$store.state.auth.user;
    },
    showCloseButton() {
      return this.$navigation && this.$navigation.canPop();
    },
    directMessageLink() {
      return this.$router.getDMLink(this.$matrix.currentUser, this.$config);
    },
    shareSupported() {
      return !!navigator.share;
    },
  },
  watch: {
    user: {
      handler() {
        // Reset manual errors
        this.userErrorMessage = null;
      },
      deep: true,
    }
  },
  methods: {
    defaultData() {
      return {
        user: new User("", util.randomPass()),
        isValid: false,
        loading: false,
        message: "",
        userErrorMessage: null,
        hasError: false,
        currentLoginServer: "",
        loadingLoginFlows: false,
        loginFlows: null,
        showQRCopiedToast: false
      };
    },
    goHome() {
      this.$navigation.push({ name: "Home" }, -1);
    },
    getDifferentLink() {
      this.$store.dispatch("logout");
      this.$nextTick(() => {
        // Reset
        const obj = this.defaultData();
        Object.keys(obj).forEach(k => this[k] = obj[k]);
        this.$refs.form.reset();
      })
    },
    goToLoginPage() {
      this.$navigation.push({ name: "Login", params: { showCreateRoomOption: false, redirect: "GetLink" } }, 1);
    },
    handleLogin() {
      if (this.user.user_id && this.user.password) {
        // Reset errors
        this.message = null;

        // Is it a full matrix user id? Modify a copy, so that the UI will still show the full ID.
        const userDisplayName = this.user.user_id;

        var user = Object.assign({}, this.user);

        let prefix = userDisplayName.toLowerCase().replaceAll(" ", "-").replaceAll(util.invalidUserIdChars(), "");
        if (prefix.length == 0) {
          prefix = this.$config.userIdPrefix;
          user.user_id = util.randomUser(prefix);
        } else {
          // We first try with a username that is just a processed version of the display name.
          // If it is already taken, try again with random characters appended.
          user.user_id = prefix;
          prefix = prefix + "-";
        }

        this.loading = true;

        this.loadLoginFlows().then(() => {
          return this.$store.dispatch("createUser", { user, registrationFlowHandler: this.$refs.interactiveAuth.registrationFlowHandler })
        })
          .then(
            (ignoreduser) => {
              this.$matrix.setUserDisplayName(userDisplayName);
            },
            (error) => {
              this.message =
                (error.data && error.data.error) ||
                error.message ||
                error.toString();
              if (error.data && error.data.errcode === 'M_FORBIDDEN') {
                this.message = this.$i18n.messages[this.$i18n.locale].login.invalid_message;
                this.hasError = true;
              } else if (error.data && error.data.errcode === 'M_USER_IN_USE') {
                // Try again with (other/new) random chars appended
                user.user_id = util.randomUser(prefix);
                return this.$store.dispatch("createUser", { user, registrationFlowHandler: this.$refs.interactiveAuth.registrationFlowHandler }).then(
                  (ignoreduser) => {
                    this.$matrix.setUserDisplayName(userDisplayName);
                  },
                  (error) => {
                    this.message =
                      (error.data && error.data.error) ||
                      error.message ||
                      error.toString();
                    if (error.data && error.data.errcode === 'M_FORBIDDEN') {
                      this.message = this.$i18n.messages[this.$i18n.locale].login.invalid_message;
                      this.hasError = true;
                    }
                  }
                );
              }
            })
          .finally(() => {
            this.loading = false;
          })
      }
    },
    handleCreateRoom() {
      this.$navigation.push({ name: "CreateRoom" });
    },
    onUsernameEnter() {
      this.handleLogin();
    },
    loadLoginFlows() {
      var user = Object.assign({}, this.user);
      util.getMatrixBaseUrl(user, this.$config)
        .then((baseUrl) => {
          if (baseUrl !== this.currentLoginServer) {
            this.currentLoginServer = baseUrl;
            this.loadingLoginFlows = true;

            const matrixClient = sdk.createClient({ baseUrl: baseUrl });
            return matrixClient.loginFlows().then((response) => {
              console.log("FLOWS", response.flows);
              this.loginFlows = response.flows.filter(this.supportedLoginFlow);
              this.loadingLoginFlows = false;
              if (this.loginFlows.length == 0) {
                this.message = this.$t('login.no_supported_flow')
                this.hasError = true;
              } else {
                this.message = "";
                this.hasError = false;
              }
            });
          } else {
            return Promise.resolve();
          }
        })
    },
    supportedLoginFlow(flow) {
      return ["m.login.password"].includes(flow.type);
    },
    shareLink() {
      const canvas = this.$refs.qr.$refs.roomQr;
      if (canvas) {
        canvas.toBlob((blob) => {
          let file = new File([blob], encodeURIComponent(this.$matrix.currentUserDisplayName || User.localPart(this.currentUser.user_id)) + ".png", { type: "image/png" })
          const shareData = { files: [file] };
          if (navigator.canShare && navigator.canShare(shareData)) {
            navigator.share(shareData);
          }
        }, 'image/png');
      }
    },
    copyQRImage(canvas) {
      if (canvas && typeof window.ClipboardItem !== "undefined" && navigator.clipboard) {
        canvas.toBlob(blob => {
          const clipboardItemInput = new window.ClipboardItem({ "image/png": blob });
          navigator.clipboard.write([clipboardItemInput]).then(() => {
            this.showQRCopiedToast = true;
            setTimeout(() => {
              this.showQRCopiedToast = false;
            }, 3000);
          }).catch(err => console.error(err));
        });
      }
    }
  },
};
</script>

<style lang="scss">
@import "@/assets/css/getlink.scss";
</style>