<template>
  <QuickNav selected="Projects"></QuickNav>
  <section id="Content" class="p-6 pb-24">
    <!-- Heading -->
    <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
      Your Plans
    </h1>

    <!-- Quick Search -->
    <form id="QuickSearch" class="mb-4 flex">
      <input
        type="text"
        placeholder="Search…"
        class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2"
      />
      <button
        class="px-4 rounded-r bg-slate-200 border border-l-0 border-slate-400"
      >
        <fa icon="magnifying-glass" class="fa-fw"></fa>
      </button>
    </form>

    <!-- New Project -->
    <button
      class="fixed right-6 bottom-24 text-center text-4xl leading-none bg-blue-600 text-white w-14 py-2.5 rounded-full"
      @click="onClickNewProject()"
    >
      <fa icon="plus" class="fa-fw"></fa>
    </button>

    <!-- Loading Animation -->
    <div
      class="fixed left-6 bottom-24 text-center text-4xl leading-none bg-slate-400 text-white w-14 py-2.5 rounded-full"
      v-if="isLoading"
    >
      <fa icon="spinner" class="fa-spin-pulse"></fa>
    </div>

    <!-- Results List -->
    <InfiniteScroll @reached-bottom="loadMoreData">
      <ul>
        <li
          class="border-b border-slate-300"
          v-for="project in projects"
          :key="project.handleId"
        >
          <a
            @click="onClickLoadProject(project.handleId)"
            class="block py-4 flex gap-4"
          >
            <div class="flex-none w-12">
              <img
                src="https://picsum.photos/200/200?random=1"
                class="w-full rounded"
              />
            </div>

            <div class="grow overflow-hidden">
              <h2 class="text-base font-semibold">{{ project.name }}</h2>
              <div class="text-sm truncate">
                {{ project.description }}
              </div>
            </div>
          </a>
        </li>
      </ul>
    </InfiniteScroll>
    <AlertMessage
      :alertTitle="alertTitle"
      :alertMessage="alertMessage"
    ></AlertMessage>
  </section>
</template>

<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { accountsDB, db } from "@/db";
import { AccountsSchema } from "@/db/tables/accounts";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto";
import { IIdentifier } from "@veramo/core";
import InfiniteScroll from "@/components/InfiniteScroll";
import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav";

@Component({
  components: { InfiniteScroll, AlertMessage, QuickNav },
})
export default class ProjectsView extends Vue {
  apiServer = "";
  projects: ProjectData[] = [];
  current: IIdentifier;
  isLoading = false;
  alertTitle = "";
  alertMessage = "";
  accounts: AccountsSchema;
  numAccounts = 0;

  async beforeCreate() {
    accountsDB.open();
    this.accounts = accountsDB.accounts;
    this.numAccounts = await this.accounts.count();
  }

  /**
   * Core project data loader
   * @param url the url used to fetch the data
   * @param token Authorization token
   **/
  async dataLoader(url: string, token: string) {
    const headers: { [key: string]: string } = {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    };

    try {
      this.isLoading = true;
      const resp = await this.axios.get(url, { headers });
      if (resp.status === 200 || !resp.data.data) {
        const plans: ProjectData[] = resp.data.data;
        for (const plan of plans) {
          const { name, description, handleId = plan.fullIri, rowid } = plan;
          this.projects.push({ name, description, handleId, rowid });
        }
      } else {
        console.log("Bad server response & data:", resp.status, resp.data);
        throw Error("Failed to get projects from the server.");
      }
    } catch (error) {
      console.error("Got error loading projects:", error.message);
      this.alertTitle = "Error";
      this.alertMessage = "Got an error loading projects:" + error.message;
    } finally {
      this.isLoading = false;
    }
  }

  /**
   * Data loader used by infinite scroller
   * @param payload is the flag from the InfiniteScroll indicating if it should load
   **/
  async loadMoreData(payload: boolean) {
    if (this.projects.length > 0 && payload) {
      const latestProject = this.projects[this.projects.length - 1];
      const url = `${this.apiServer}/api/v2/report/plansByIssuer?beforeId=${latestProject.rowid}`;
      const token = await accessToken(this.current);
      await this.dataLoader(url, token);
    }
  }

  /**
   * Handle clicking on a project entry found in the list
   * @param id of the project
   **/
  onClickLoadProject(id: string) {
    localStorage.setItem("projectId", id);
    const route = {
      name: "project",
    };
    this.$router.push(route);
  }

  /**
   * Load projects initially
   * @param identity of the user
   **/
  async LoadProjects(identity: IIdentifier) {
    const url = `${this.apiServer}/api/v2/report/plansByIssuer`;
    const token: string = await accessToken(identity);
    await this.dataLoader(url, token);
  }

  public async getIdentity(activeDid) {
    await accountsDB.open();
    const account = await accountsDB.accounts
      .where("did")
      .equals(activeDid)
      .first();
    const identity = JSON.parse(account?.identity || "null");

    if (!identity) {
      throw new Error(
        "Attempted to load project records with no identity available.",
      );
    }
    return identity;
  }

  /**
   * 'created' hook runs when the Vue instance is first created
   **/
  async created() {
    try {
      await db.open();
      const settings = await db.settings.get(MASTER_SETTINGS_KEY);
      const activeDid = settings?.activeDid || "";
      this.apiServer = settings?.apiServer || "";

      if (this.numAccounts === 0) {
        console.error("No accounts found.");
        this.alertTitle = "Error";
        this.alertMessage = "You need an identity to load your projects.";
      } else {
        const identity = await this.getIdentity(activeDid);
        this.current = identity;
        this.LoadProjects(identity);
      }
    } catch (err) {
      console.log("Error initializing:", err);
      this.alertTitle = "Error";
      this.alertMessage = "Something went wrong loading your projects.";
    }
  }

  /**
   * Handling clicking on the new project button
   **/
  onClickNewProject(): void {
    localStorage.removeItem("projectId");
    const route = {
      name: "new-edit-project",
    };
    this.$router.push(route);
  }
}
</script>
