<template>
  <QuickNav selected="Invite" />
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <div v-if="acceptInput" class="text-center mt-4">
      <p>That invitation did not work.</p>
      <p class="mt-2">
        Go back to your invite message and copy the entire text, then paste it
        here.
      </p>
      <p class="mt-2">
        If the link looks correct, try Chrome. (For example, iOS may have cut
        off the invite data, or it may have shown a preview that stole your
        invite.) If it still complains, you may need the person who invited you
        to send a new one.
      </p>
      <textarea
        v-model="inputJwt"
        placeholder="Paste invitation..."
        class="mt-4 border-2 border-gray-300 p-2 rounded"
        cols="30"
        @input="() => checkInvite(inputJwt)"
      />
      <br />
      <button
        @click="() => processInvite(inputJwt, true)"
        class="ml-2 p-2 bg-blue-500 text-white rounded"
      >
        Submit
      </button>
    </div>
    <div
      v-if="checkingInvite"
      class="text-lg text-center font-light relative px-7"
    >
      <fa icon="spinner" class="fa-spin-pulse" />
      Loading&hellip;
    </div>
  </section>
</template>

<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";

import QuickNav from "@/components/QuickNav.vue";
import { NotificationIface } from "@/constants/app";
import {
  db,
  logConsoleAndDb,
  retrieveSettingsForActiveAccount,
} from "@/db/index";
import { decodeEndorserJwt } from "@/libs/crypto/vc";
import { errorStringForLog } from "@/libs/endorserServer";
import { generateSaveAndActivateIdentity } from "@/libs/util";

@Component({ components: { QuickNav } })
export default class InviteOneAcceptView extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;

  acceptInput: boolean = false;
  activeDid: string = "";
  apiServer: string = "";
  checkingInvite: boolean = true;
  inputJwt: string = "";

  async mounted() {
    this.checkingInvite = true;
    await db.open();
    const settings = await retrieveSettingsForActiveAccount();
    this.activeDid = settings.activeDid || "";
    this.apiServer = settings.apiServer || "";

    if (!this.activeDid) {
      this.activeDid = await generateSaveAndActivateIdentity();
    }

    const jwt = window.location.pathname.substring(
      "/invite-one-accept/".length,
    );
    await this.processInvite(jwt, false);

    this.checkingInvite = false;
  }

  // process the invite JWT and/or text message containing the URL with the JWT
  async processInvite(jwtInput: string, notifyOnFailure: boolean) {
    this.checkingInvite = true;

    try {
      let jwt: string = jwtInput ?? "";

      // parse the string: extract the URL or JWT if surrounded by spaces
      // and then extract the JWT from the URL
      const urlMatch = jwtInput.match(/(https?:\/\/[^\s]+)/);
      if (urlMatch && urlMatch[1]) {
        // extract the JWT from the URL, meaning any character except "?"
        const internalMatch = urlMatch[1].match(/\/invite-one-accept\/([^?]+)/);
        if (internalMatch && internalMatch[1]) {
          jwt = internalMatch[1];
        }
      } else {
        // extract the JWT (which starts with "ey") if it is surrounded by other input
        const spaceMatch = jwtInput.match(/(ey[\w.-]+)/);
        if (spaceMatch && spaceMatch[1]) {
          jwt = spaceMatch[1];
        }
      }

      if (!jwt) {
        if (notifyOnFailure) {
          this.$notify(
            {
              group: "alert",
              type: "danger",
              title: "Missing invite",
              text: "There was no invite. Paste the entire text that has the link.",
            },
            5000,
          );
        }
        this.acceptInput = true;
      } else {
        //const payload: JWTPayload =
        decodeEndorserJwt(jwt);

        // That's good enough for an initial check.
        // Send them to the contacts page to finish, with inviteJwt in the query string.
        (this.$router as Router).push({
          name: "contacts",
          query: { inviteJwt: jwt },
        });
      }
    } catch (error) {
      const fullError = "Error accepting invite: " + errorStringForLog(error);
      logConsoleAndDb(fullError, true);
      if (notifyOnFailure) {
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "There was an error processing that invite.",
          },
          3000,
        );
      }
      this.acceptInput = true;
    }
    this.checkingInvite = false;
  }

  // check the invite JWT
  async checkInvite(jwtInput: string) {
    if (
      jwtInput.endsWith("invite-one-accept") ||
      jwtInput.endsWith("invite-one-accept/")
    ) {
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "That is only part of the invite link; it's missing data at the end. Try another way to get the full link.",
        },
        5000,
      );
    }
  }
}
</script>