<template>
  <QuickNav selected="Contacts" />
  <TopMessage />

  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Heading -->
    <h1 id="ViewHeading" class="text-4xl text-center font-light mb-8">
      Meeting Members
    </h1>

    <!-- Loading Animation -->
    <div
      class="mt-16 text-center text-4xl bg-slate-400 text-white w-14 py-2.5 rounded-full mx-auto"
      v-if="isLoading"
    >
      <fa icon="spinner" class="fa-spin-pulse"></fa>
    </div>

    <!-- Error State -->
    <div v-else-if="errorMessage">
      <div class="text-center text-red-600 py-8">
        {{ errorMessage }}
      </div>
      <div class="text-center">
        For authorization, wait for your meeting organizer to approve you.
      </div>
    </div>

    <!-- Members List -->
    <MembersList v-else :password="password" @error="handleError" />
  </section>

  <UserNameDialog
    ref="userNameDialog"
    :callback-on-cancel="true"
    sharing-explanation="This is encrypted and shared only with people in this meeting."
  />
</template>

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

import QuickNav from "@/components/QuickNav.vue";
import TopMessage from "@/components/TopMessage.vue";
import MembersList from "@/components/MembersList.vue";
import UserNameDialog from "@/components/UserNameDialog.vue";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "@/db/index";
import { encryptMessage } from "@/libs/crypto";
import {
  errorStringForLog,
  getHeaders,
  serverMessageForUser,
} from "@/libs/endorserServer";
import { generateSaveAndActivateIdentity } from "@/libs/util";

@Component({
  components: {
    QuickNav,
    TopMessage,
    MembersList,
    UserNameDialog,
  },
})
export default class OnboardMeetingMembersView extends Vue {
  activeDid = "";
  apiServer = "";
  errorMessage = "";
  firstName = "";
  isRegistered = false;
  isLoading = true;

  $refs!: {
    userNameDialog: InstanceType<typeof UserNameDialog>;
  };

  get groupId(): string {
    return (this.$route as RouteLocation).params.groupId as string;
  }

  get password(): string {
    return (this.$route as RouteLocation).query.password as string;
  }

  async created() {
    if (!this.groupId) {
      this.errorMessage = "The group info is missing. Go back and try again.";
      return;
    }
    if (!this.password) {
      this.errorMessage = "The password is missing. Go back and try again.";
      return;
    }
    const settings = await retrieveSettingsForActiveAccount();
    this.activeDid = settings.activeDid || "";
    this.apiServer = settings.apiServer || "";
    this.firstName = settings.firstName || "";
    this.isRegistered = settings.isRegistered || false;
    try {
      if (!this.activeDid) {
        this.activeDid = await generateSaveAndActivateIdentity();
        this.isRegistered = false;
      }
      const headers = await getHeaders(this.activeDid);
      const response = await this.axios.get(
        `${this.apiServer}/api/partner/groupOnboardMember`,
        { headers },
      );
      const member = response.data?.data;
      if (!member) {
        if (!this.firstName) {
          this.$refs.userNameDialog.open(this.addMemberToMeeting);
          // addMemberToMeeting sets isLoading to false
        } else {
          await this.addMemberToMeeting(this.firstName);
          // addMemberToMeeting sets isLoading to false
        }
      } else if (String(member.groupId) !== this.groupId) {
        this.errorMessage =
          "You are already in a different meeting. Reload or go back and try again.";
        this.isLoading = false;
      } else {
        // must be already in the right meeting
        if (!this.firstName) {
          this.$refs.userNameDialog.open(this.updateMemberInMeeting);
          // updateMemberInMeeting sets isLoading to false
        } else {
          await this.updateMemberInMeeting(this.firstName);
          // updateMemberInMeeting sets isLoading to false
        }
      }
    } catch (error) {
      this.errorMessage =
        serverMessageForUser(error) ||
        "There was an error checking for that meeting. Reload or go back and try again.";
      logConsoleAndDb(
        "Error checking meeting: " + errorStringForLog(error),
        true,
      );
      this.isLoading = false;
    }
  }

  async addMemberToMeeting(name?: string) {
    if (name != null) {
      this.firstName = name;
    }

    const memberData = {
      name: this.firstName,
      did: this.activeDid,
      isRegistered: this.isRegistered,
    };
    const memberDataString = JSON.stringify(memberData);
    const encryptedMemberData = await encryptMessage(
      memberDataString,
      this.password,
    );

    const headers = await getHeaders(this.activeDid);
    try {
      await this.axios.post(
        `${this.apiServer}/api/partner/groupOnboardMember`,
        { groupId: this.groupId, content: encryptedMemberData },
        { headers },
      );
    } catch (error) {
      logConsoleAndDb(
        "Error adding member to meeting: " + errorStringForLog(error),
        true,
      );
      this.errorMessage =
        serverMessageForUser(error) ||
        "You're not in a meeting and couldn't be added to this one. Reload or go back and try again.";
    }
    this.isLoading = false;
  }

  async updateMemberInMeeting(name?: string) {
    if (name != null) {
      this.firstName = name;
    }
    const memberData = {
      name: this.firstName,
      did: this.activeDid,
      isRegistered: this.isRegistered,
    };
    const memberDataString = JSON.stringify(memberData);
    const encryptedMemberData = await encryptMessage(
      memberDataString,
      this.password,
    );
    const headers = await getHeaders(this.activeDid);
    try {
      await this.axios.put(
        `${this.apiServer}/api/partner/groupOnboardMember`,
        { content: encryptedMemberData },
        { headers },
      );
    } catch (error) {
      logConsoleAndDb(
        "Error updating member in meeting: " + errorStringForLog(error),
        true,
      );
      this.errorMessage =
        serverMessageForUser(error) ||
        "There was an error updating your name. Reload or go back and try again.";
    }
    this.isLoading = false;
  }

  handleError(message: string) {
    this.errorMessage = message;
  }
}
</script>