<template>
  <QuickNav />
  <!-- CONTENT -->
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Breadcrumb -->
    <div id="ViewBreadcrumb" class="mb-8">
      <h1 class="text-lg text-center font-light relative px-7">
        <!-- Back -->
        <button
          @click="$router.go(-1)"
          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
        >
          <fa icon="chevron-left" class="fa-fw" />
        </button>
        <span
          v-if="
            libsUtil.isGiveRecordTheUserCanConfirm(
              veriClaim,
              activeDid,
              confirmerIdList,
            )
          "
        >
          Do you agree?
        </span>
        <span v-else> Details </span>
      </h1>
    </div>

    <div v-if="detailsForGive">
      <div class="flex justify-center">
        <button
          class="col-span-1 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
          v-if="
            libsUtil.isGiveRecordTheUserCanConfirm(
              veriClaim,
              activeDid,
              confirmerIdList,
            )
          "
          @click="confirmConfirmClaim()"
        >
          Confirm
          <fa icon="circle-check" class="ml-2 text-white cursor-pointer" />
        </button>
        <button
          v-else
          @click="notifyWhyCannotConfirm()"
          class="col-span-1 bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
        >
          Confirm
          <fa icon="circle-check" class="ml-2 text-white cursor-pointer" />
        </button>
        <a
          class="col-span-1 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white ml-2 px-4 py-2 rounded-md"
          :href="urlForNewGive"
        >
          Record One of Your Own
        </a>
      </div>

      <!-- Details -->
      <div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mt-4">
        <div class="block flex gap-4 overflow-hidden">
          <div class="overflow-hidden">
            <div class="text-sm">
              <div>
                <fa icon="arrow-down" class="fa-fw text-slate-400" />
                {{ giverName }}
              </div>
              <div class="ml-6">gave</div>
              <div v-if="veriClaim.claim?.object">
                <fa icon="hand-holding-dollar" class="fa-fw text-slate-400" />
                {{
                  displayAmount(
                    veriClaim.claim.object.unitCode,
                    veriClaim.claim.object.amountOfThisGood,
                  )
                }}
                600
              </div>
              <div>
                <fa icon="message" class="fa-fw text-slate-400" />
                {{ veriClaim.claim?.object ? "and" : "" }}
                {{ veriClaim.claim?.description }}
              </div>
              <div>
                <fa icon="arrow-up" class="fa-fw text-slate-400" />
                to {{ recipientName }}
              </div>
              <div>
                <fa icon="calendar" class="fa-fw text-slate-400" />
                {{ veriClaim.issuedAt?.replace(/T/, " ").replace(/Z/, " UTC") }}
              </div>

              <!-- Fullfills Links -->

              <!-- fullfills links for a give -->
              <div class="mt-2" v-if="detailsForGive?.fulfillsPlanHandleId">
                <router-link
                  :to="
                    '/project/' +
                    encodeURIComponent(detailsForGive?.fulfillsPlanHandleId)
                  "
                  class="text-blue-500 mt-2 cursor-pointer"
                  target="_blank"
                >
                  This fulfills a bigger plan
                  <fa icon="arrow-up-right-from-square" class="fa-fw" />
                </router-link>
              </div>
              <!-- if there's another, it's probably fulfilling an offer, too -->
              <div
                v-if="
                  detailsForGive?.fulfillsType &&
                  detailsForGive?.fulfillsType !== 'PlanAction' &&
                  detailsForGive?.fulfillsHandleId
                "
              >
                <!-- router-link to /claim/ only changes URL path -->
                <router-link
                  :to="
                    '/claim/' +
                    encodeURIComponent(detailsForGive?.fulfillsHandleId)
                  "
                  class="text-blue-500 mt-2 cursor-pointer"
                  target="_blank"
                >
                  This fulfills
                  {{
                    capitalizeAndInsertSpacesBeforeCapsWithAPrefix(
                      detailsForGive.fulfillsType,
                    )
                  }}
                  <fa icon="arrow-up-right-from-square" class="fa-fw" />
                </router-link>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="mt-2">
        <fa icon="comment" class="fa-fw text-slate-400" />
        {{ issuerName }} said that.
      </div>

      <div class="flex justify-center">
        <button
          v-if="
            libsUtil.isGiveRecordTheUserCanConfirm(
              veriClaim,
              activeDid,
              confirmerIdList,
            )
          "
          @click="confirmConfirmClaim()"
          class="col-span-1 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
        >
          Confirm
          <fa icon="circle-check" class="ml-2 text-white cursor-pointer" />
        </button>
        <button
          v-else
          @click="notifyWhyCannotConfirm()"
          class="col-span-1 bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
        >
          Confirm
          <fa icon="circle-check" class="ml-2 text-white cursor-pointer" />
        </button>
        <a
          class="col-span-1 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white ml-2 px-4 py-2 rounded-md"
          :href="urlForNewGive"
        >
          Record One of Your Own
        </a>
      </div>

      <div v-if="libsUtil.isGiveAction(veriClaim)" class="mt-4">
        <h2 class="font-bold uppercase text-xl mt-8 mb-2">Confirmations</h2>

        <span v-if="totalConfirmers() === 0">Nobody has confirmed this.</span>
        <span v-else-if="totalConfirmers() === 1">
          One person has confirmed this.
        </span>
        <span v-else>
          {{ totalConfirmers() }} people have confirmed this.
        </span>

        <div v-if="totalConfirmers() > 0">
          <div
            v-if="
              confirmerIdList.length === 0 && confsVisibleToIdList.length === 0
            "
          >
            Nobody that you know confirmed this claim, nor do they have any
            confirmers in their network.
          </div>

          <div
            v-if="
              confirmerIdList.length === 0 && confsVisibleToIdList.length > 0
            "
          >
            <!-- Only show if this person has links to confirmers (below). -->
            Nobody that you know has issued or confirmed this claim.
          </div>
          <div v-if="confirmerIdList.length > 0">
            The following people have issued or confirmed this claim.
            <ul class="ml-4">
              <li
                v-for="confirmerId in confirmerIdList"
                :key="confirmerId"
                class="list-disc ml-4"
              >
                <div class="flex gap-4">
                  <div class="grow overflow-hidden">
                    <div class="text-sm">
                      {{ didInfo(confirmerId) }}
                      <span v-if="!serverUtil.isEmptyOrHiddenDid(confirmerId)">
                        <button
                          @click="
                            copyToClipboard(
                              'The DID of ' + confirmerId,
                              confirmerId,
                            )
                          "
                        >
                          <fa icon="copy" class="text-slate-400 fa-fw" />
                        </button>
                      </span>
                    </div>
                  </div>
                </div>
              </li>
            </ul>
          </div>

          <!--
           Never need to show this message:
           "Nobody that you know can see someone who has confirmed this claim."

           If there is nobody in the confirmerIdList then we'll show the combined "nobody" message.
           If there is somebody in the confirmerIdList then that's all they need to show.
           -->

          <!-- Now show anyone linked to confirmers. -->
          <div v-if="confsVisibleToIdList.length > 0">
            The following people can connect you with people who have issued or
            confirmed this claim.
            <ul class="ml-4">
              <li
                v-for="confsVisibleTo in confsVisibleToIdList"
                :key="confsVisibleTo"
                class="list-disc ml-4"
              >
                <div class="flex gap-4">
                  <div class="grow overflow-hidden">
                    <div class="text-sm">
                      {{ didInfo(confsVisibleTo) }}
                      <span
                        v-if="!serverUtil.isEmptyOrHiddenDid(confsVisibleTo)"
                      >
                        <button
                          @click="
                            copyToClipboard(
                              'The DID of ' + confsVisibleTo,
                              confsVisibleTo,
                            )
                          "
                        >
                          <fa icon="copy" class="text-slate-400 fa-fw" />
                        </button>
                      </span>
                    </div>
                  </div>
                </div>
              </li>
            </ul>
          </div>
        </div>

        <!-- explain if user cannot confirm -->
        <!-- Note that these conditions are mirrored in userCanConfirm(). -->
        <div v-if="confirmerIdList.includes(activeDid)">
          You have confirmed this claim.
        </div>
        <div v-else-if="veriClaim.issuer == activeDid">
          You cannot confirm this because you issued this claim, so you already
          count as confirming it.
        </div>
        <div v-else-if="serverUtil.containsHiddenDid(veriClaim.claim)">
          You cannot confirm this because it contains hidden identifiers.
        </div>
      </div>

      <h2
        class="font-bold uppercase text-xl text-blue-500 mt-8 mb-2 cursor-pointer"
        @click="showDetails = !showDetails"
      >
        {{ serverUtil.containsHiddenDid(veriClaim) ? "Visible " : "" }}Details
        <span v-if="!showDetails">...</span>
      </h2>
      <div v-if="showDetails">
        <div
          v-if="
            serverUtil.containsHiddenDid(veriClaim) &&
            R.isEmpty(veriClaimDidsVisible)
          "
          class="mb-2"
        >
          Some of the details are not visible to you; they show as "HIDDEN".
          They are not visible to any of your direct contacts, either.
          <span v-if="canShare">
            If you'd like to ask any of your contacts to take a look and see if
            their contacts can see more details,
            <a @click="onClickShareClaim()" class="text-blue-500"
              >click to send them this info</a
            >
            and see if they are willing to make an introduction.
          </span>
          <span v-else>
            If you'd like to ask any of your contacts to take a look and see if
            their contacts can see more details,
            <a
              @click="copyToClipboard('Location', windowLocation.href)"
              class="text-blue-500"
              >share this page with them</a
            >
            and see if they are willing to make an introduction.
          </span>
        </div>

        <div v-if="!R.isEmpty(veriClaimDidsVisible)">
          Some of the details are not visible to you but they are visible to
          some of your contacts.
          <span v-if="canShare">
            If you'd like an introduction,
            <a @click="onClickShareClaim()" class="text-blue-500"
              >click to share the information with them and ask if they'll tell
              you more about the participants.</a
            >
          </span>
          <span v-else>
            If you'd like an introduction,
            <a
              @click="copyToClipboard('Location', windowLocation.href)"
              class="text-blue-500"
              >share this page with them and ask if they'll tell you more about
              about the participants.</a
            >
          </span>

          <div
            v-for="(visibleDidPath, index) of Object.keys(veriClaimDidsVisible)"
            :key="index"
            class="list-disc p-4"
          >
            <div class="text-sm">
              <fa icon="minus" class="fa-fw" />
              The {{ visibleDidPath }} is visible to:
            </div>
            <div class="ml-12 p-1">
              <ul>
                <li
                  v-for="(visDid, idx2) of veriClaimDidsVisible[visibleDidPath]"
                  :key="idx2"
                  class="list-disc"
                >
                  <div class="text-sm mt-2">
                    <span>
                      {{ didInfo(visDid) }}
                      <span v-if="!serverUtil.isEmptyOrHiddenDid(visDid)">
                        <button
                          @click="
                            copyToClipboard('The DID of ' + visDid, visDid)
                          "
                        >
                          <fa icon="copy" class="text-slate-400 fa-fw" />
                        </button>
                      </span>
                      <span v-if="veriClaim.publicUrls?.[visDid]"
                        >, found at
                        <fa icon="globe" class="fa-fw text-slate-400" />
                        <a
                          :href="veriClaim.publicUrls?.[visDid]"
                          class="text-blue-500"
                          >{{
                            veriClaim.publicUrls[visDid].substring(
                              veriClaim.publicUrls[visDid].indexOf("//") + 2,
                            )
                          }}
                        </a>
                      </span>
                    </span>
                  </div>
                </li>
              </ul>
            </div>
          </div>
        </div>
        <!-- Keep the dump contents directly between > and < to avoid weird spacing. -->
        <pre
          class="text-sm overflow-x-scroll px-4 py-3 bg-slate-100 rounded-md"
          >{{ veriClaimDump }}</pre
        >
      </div>
    </div>
    <div v-else>This does not have details to confirm.</div>

    <div class="mt-4">
      <a
        @click="showClaimPage(veriClaim.id)"
        class="text-blue-500 cursor-pointer"
      >
        <fa icon="file-lines" class="pl-2" />
        All Generic Info
      </a>
    </div>
  </section>
</template>

<script lang="ts">
import { AxiosError, RawAxiosRequestHeaders } from "axios";
import * as yaml from "js-yaml";
import * as R from "ramda";
import { IIdentifier } from "@veramo/core";
import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core";

import GiftedDialog from "@/components/GiftedDialog.vue";
import QuickNav from "@/components/QuickNav.vue";
import { NotificationIface } from "@/constants/app";
import { accountsDB, db } from "@/db/index";
import { Account } from "@/db/tables/accounts";
import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto";
import * as serverUtil from "@/libs/endorserServer";
import { displayAmount, GiverReceiverInputInfo } from "@/libs/endorserServer";
import * as libsUtil from "@/libs/util";
import { isGiveAction } from "@/libs/util";

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

  accountIdentityStr: string = "null";
  activeDid = "";
  allMyDids: Array<string> = [];
  allContacts: Array<Contact> = [];
  apiServer = "";

  canShare = false;
  confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
  confsVisibleErrorMessage = "";
  confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer
  detailsForGive = null;
  giverName = "";
  issuerName = "";
  numConfsNotVisible = 0; // number of hidden DIDs in the confirmerIdList, minus the issuer if they aren't visible
  recipientName = "";
  showDetails = false;
  urlForNewGive = "";
  veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
  veriClaimDump = "";
  veriClaimDidsVisible = {};
  windowLocation = window.location;

  R = R;
  yaml = yaml;
  libsUtil = libsUtil;
  serverUtil = serverUtil;

  resetThisValues() {
    this.confirmerIdList = [];
    this.confsVisibleErrorMessage = "";
    this.confsVisibleToIdList = [];
    this.detailsForGive = null;
    this.numConfsNotVisible = 0;
    this.urlForNewGive = "";
    this.veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
    this.veriClaimDump = "";
  }

  async mounted() {
    await db.open();
    const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings;
    this.activeDid = settings?.activeDid || "";
    this.apiServer = settings?.apiServer || "";
    this.allContacts = await db.contacts.toArray();

    await accountsDB.open();
    const accounts = accountsDB.accounts;
    const accountsArr: Array<Account> = await accounts?.toArray();
    this.allMyDids = accountsArr.map((acc) => acc.did);
    const account = accountsArr.find((acc) => acc.did === this.activeDid);
    this.accountIdentityStr = (account?.identity as string) || "null";
    const identity = JSON.parse(this.accountIdentityStr);

    const pathParam = window.location.pathname.substring(
      "/confirm-gift/".length,
    );
    let claimId;
    if (pathParam) {
      claimId = decodeURIComponent(pathParam);
      await this.loadClaim(claimId, identity);
    } else {
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "No claim ID was provided.",
        },
        3000,
      );
    }

    // When Chrome compatibility is fixed https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API#api.navigator.canshare
    // then use this truer check: navigator.canShare && navigator.canShare()
    this.canShare = !!navigator.share;
  }

  // insert a space before any capital letters except the initial letter
  // (and capitalize initial letter, just in case)
  capitalizeAndInsertSpacesBeforeCaps(text: string) {
    return !text
      ? ""
      : text[0].toUpperCase() + text.substr(1).replace(/([A-Z])/g, " $1");
  }

  capitalizeAndInsertSpacesBeforeCapsWithAPrefix(text: string) {
    const word = this.capitalizeAndInsertSpacesBeforeCaps(text);
    if (word) {
      // if the word starts with a vowel, use "an" instead of "a"
      const firstLetter = word[0].toLowerCase();
      const vowels = ["a", "e", "i", "o", "u"];
      const particle = vowels.includes(firstLetter) ? "an" : "a";
      return particle + " " + word;
    } else {
      return "";
    }
  }

  totalConfirmers() {
    return (
      this.numConfsNotVisible +
      this.confirmerIdList.length +
      this.confsVisibleToIdList.length
    );
  }

  public async getIdentity(activeDid: string): Promise<IIdentifier> {
    await accountsDB.open();
    const account = (await accountsDB.accounts
      .where("did")
      .equals(activeDid)
      .first()) as Account;
    const identity = JSON.parse(account?.identity || "null");

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

  public async getHeaders(identity: IIdentifier) {
    const headers: RawAxiosRequestHeaders = {
      "Content-Type": "application/json",
    };
    if (identity) {
      const token = await accessToken(identity);
      headers["Authorization"] = "Bearer " + token;
    }
    return headers;
  }

  // Isn't there a better way to make this available to the template?
  didInfo(did: string | undefined) {
    return serverUtil.didInfo(
      did,
      this.activeDid,
      this.allMyDids,
      this.allContacts,
    );
  }

  async loadClaim(claimId: string, identity: IIdentifier) {
    const urlPath = libsUtil.isGlobalUri(claimId)
      ? "/api/claim/byHandle/"
      : "/api/claim/";
    const url = this.apiServer + urlPath + encodeURIComponent(claimId);

    try {
      const headers = await this.getHeaders(identity);
      const resp = await this.axios.get(url, { headers });
      // resp.data is:
      // - a Jwt from https://api.endorser.ch/api-docs/
      // - with a Give from https://endorser.ch/doc/html/transactions.html#id3
      if (resp.status === 200) {
        this.veriClaim = resp.data;
        this.veriClaimDump = yaml.dump(this.veriClaim);
        this.veriClaimDidsVisible = libsUtil.findAllVisibleToDids(
          this.veriClaim,
          true,
        );
      } else {
        // actually, axios typically throws an error so we never get here
        console.error("Error getting claim:", resp);
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "There was a problem retrieving that claim.",
          },
          3000,
        );
        return;
      }

      // retrieve more details on Give, Offer, or Plan
      if (this.veriClaim.claimType !== "GiveAction") {
        // no need to go further... this page is for gifts
        return;
      }

      this.issuerName = this.didInfo(this.veriClaim.issuer);

      this.urlForNewGive = "/gifted-details?";
      if (this.veriClaim.claim.object) {
        if (this.veriClaim.claim.object.amountOfThisGood) {
          this.urlForNewGive +=
            "&amountInput=" +
            encodeURIComponent(
              String(this.veriClaim.claim.object.amountOfThisGood),
            );
        }
        if (this.veriClaim.claim.object.unitCode) {
          this.urlForNewGive +=
            "&unitCode=" +
            encodeURIComponent(this.veriClaim.claim.object.unitCode as string);
        }
      }
      if (this.veriClaim.claim.description) {
        this.urlForNewGive +=
          "&description=" +
          encodeURIComponent(this.veriClaim.claim.description as string);
      }
      this.giverName = this.didInfo(
        this.veriClaim.claim.agent?.identifier as string,
      );
      if (this.veriClaim.claim.agent) {
        this.urlForNewGive +=
          "&giverDid=" +
          encodeURIComponent(this.veriClaim.claim.agent.identifier as string) +
          "&giverName=" +
          encodeURIComponent(this.giverName);
      }
      this.recipientName = this.didInfo(
        this.veriClaim.claim.recipient?.identifier as string,
      );
      if (this.veriClaim.claim.recipient) {
        this.urlForNewGive +=
          "&recipientDid=" +
          encodeURIComponent(
            this.veriClaim.claim.recipient.identifier as string,
          ) +
          "&recipientName=" +
          encodeURIComponent(this.recipientName);
      }
      if (this.veriClaim.claim.image) {
        this.urlForNewGive +=
          "&image=" + encodeURIComponent(this.veriClaim.claim.image as string);
      }
      if (this.veriClaim.claim.fulfills) {
        this.urlForNewGive += this.fulfillsUrlSnippet(
          this.veriClaim.claim.fulfills,
        );
        if (Array.isArray(this.veriClaim.claim.fulfills)) {
          for (const fulfills of this.veriClaim.claim.fulfills) {
            console.log("adding fulfills:", fulfills);
            this.urlForNewGive += this.fulfillsUrlSnippet(fulfills);
          }
        }
      }

      const giveUrl =
        this.apiServer +
        "/api/v2/report/gives?handleId=" +
        encodeURIComponent(this.veriClaim.handleId as string);
      const giveHeaders = await this.getHeaders(identity);
      const giveResp = await this.axios.get(giveUrl, {
        headers: giveHeaders,
      });
      // giveResp.data is a Give from https://api.endorser.ch/api-docs/
      if (giveResp.status === 200) {
        this.detailsForGive = giveResp.data.data[0];
      } else {
        console.error("Error getting detailed give info:", giveResp);
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "Something went wrong retrieving gift data.",
          },
          3000,
        );
      }

      // retrieve the list of confirmers
      const confirmUrl =
        this.apiServer +
        "/api/report/issuersWhoClaimedOrConfirmed?claimId=" +
        encodeURIComponent(serverUtil.stripEndorserPrefix(claimId));
      const confirmHeaders = await this.getHeaders(identity);
      const response = await this.axios.get(confirmUrl, {
        headers: confirmHeaders,
      });
      if (response.status === 200) {
        const resultList1 = response.data.result || [];
        const resultList2 = R.reject(serverUtil.isHiddenDid, resultList1);
        const resultList3 = R.reject(
          (did: string) => did === this.veriClaim.issuer,
          resultList2,
        );
        this.confirmerIdList = resultList3;
        this.numConfsNotVisible = resultList1.length - resultList2.length;
        if (resultList3.length === resultList2.length) {
          // the issuer was not in the "visible" list so they must be hidden
          // so subtract them from the non-visible confirmers count
          this.numConfsNotVisible = this.numConfsNotVisible - 1;
        }
        this.confsVisibleToIdList =
          response.data.result.resultVisibleToDids || [];
      } else {
        this.confsVisibleErrorMessage =
          "Had problems retrieving confirmations.";
      }
    } catch (error: unknown) {
      const serverError = error as AxiosError;
      console.error("Error retrieving claim:", serverError);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "Something went wrong retrieving claim data.",
        },
        3000,
      );
    }
  }

  fulfillsUrlSnippet(object) {
    if (object["@type"] === "PlanAction") {
      return "&projectId=" + encodeURIComponent(object.identifier);
    } else if (object["@type"] === "OfferAction") {
      return "&offerId=" + encodeURIComponent(object.identifier);
    } else {
      return "";
    }
  }

  confirmConfirmClaim() {
    this.$notify(
      {
        group: "modal",
        type: "confirm",
        title: "Confirm",
        text: "Do you personally confirm that this is true?",
        onYes: async () => {
          await this.confirmClaim();
        },
      },
      -1,
    );
  }

  // similar code is found in ProjectViewView
  async confirmClaim() {
    // similar logic is found in endorser-mobile
    const goodClaim = serverUtil.removeSchemaContext(
      serverUtil.removeVisibleToDids(
        serverUtil.addLastClaimOrHandleAsIdIfMissing(
          this.veriClaim.claim,
          this.veriClaim.id,
          this.veriClaim.handleId,
        ),
      ),
    );
    const confirmationClaim: serverUtil.GenericVerifiableCredential = {
      "@context": "https://schema.org",
      "@type": "AgreeAction",
      object: goodClaim,
    };
    const result = await serverUtil.createAndSubmitClaim(
      confirmationClaim,
      await this.getIdentity(this.activeDid),
      this.apiServer,
      this.axios,
    );
    if (result.type === "success") {
      this.$notify(
        {
          group: "alert",
          type: "success",
          title: "Success",
          text: "Confirmation submitted.",
        },
        5000,
      );
    } else {
      console.error("Got error submitting the confirmation:", result);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "There was a problem submitting the confirmation. See logs for more info.",
        },
        5000,
      );
    }
  }

  showClaimPage(claimId: string) {
    const route = {
      path: "/claim/" + encodeURIComponent(claimId),
    };
    this.$router.push(route).then(async () => {
      this.resetThisValues();
      await this.loadClaim(claimId, JSON.parse(this.accountIdentityStr));
    });
  }

  openFulfillGiftDialog() {
    const giver: GiverReceiverInputInfo = {
      did: libsUtil.offerGiverDid(this.veriClaim),
    };
    (this.$refs.customGiveDialog as GiftedDialog).open(
      giver,
      undefined,
      this.veriClaim.handleId,
      "Offer fulfilled by " + (giver?.name || "someone not named"),
    );
  }

  copyToClipboard(name: string, text: string) {
    useClipboard()
      .copy(text)
      .then(() => {
        this.$notify(
          {
            group: "alert",
            type: "toast",
            title: "Copied",
            text: (name || "That") + " was copied to the clipboard.",
          },
          2000,
        );
      });
  }

  notifyWhyCannotConfirm() {
    if (!isGiveAction(this.veriClaim)) {
      this.$notify(
        {
          group: "alert",
          type: "info",
          title: "Not A Give",
          text: "This is not a giving action to confirm.",
        },
        3000,
      );
    } else if (this.confirmerIdList.includes(this.activeDid)) {
      this.$notify(
        {
          group: "alert",
          type: "info",
          title: "Already Confirmed",
          text: "You have already confirmed this claim.",
        },
        3000,
      );
    } else if (this.veriClaim.issuer == this.activeDid) {
      this.$notify(
        {
          group: "alert",
          type: "info",
          title: "Cannot Confirm",
          text: "You cannot confirm this because you issued this claim.",
        },
        3000,
      );
    } else if (serverUtil.containsHiddenDid(this.veriClaim.claim)) {
      this.$notify(
        {
          group: "alert",
          type: "info",
          title: "Cannot Confirm",
          text: "You cannot confirm this because it contains hidden identifiers.",
        },
        3000,
      );
    } else {
      this.$notify(
        {
          group: "alert",
          type: "info",
          title: "Cannot Confirm",
          text: "You cannot confirm this claim.",
        },
        3000,
      );
    }
  }

  onClickShareClaim() {
    window.navigator.share({
      title: "Help Connect Me",
      text: "I'm trying to find the full details of this claim. Can you help me?",
      url: this.windowLocation.href,
    });
  }
}
</script>
