<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
          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
          @click="$router.go(-1)"
        >
          <font-awesome icon="chevron-left" class="fa-fw" />
        </button>
        Verifiable Claim Details
      </h1>
    </div>

    <!-- Details -->
    <div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4 w-full">
      <div class="block flex gap-4 overflow-hidden w-full">
        <div class="w-full">
          <div class="flex columns-3">
            <h2 class="text-md font-bold w-full">
              {{
                capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType || "")
              }}
              <button
                v-if="
                  ['GiveAction', 'Offer', 'PlanAction'].includes(
                    veriClaim.claimType as string,
                  ) && veriClaim.issuer === activeDid
                  // a PlanAction agent also could edit one of those,
                  // but rather than add more Plan-specific logic to detect the agent
                  // we'll let them click the Project link and edit from there
                "
                title="Edit"
                data-testId="editClaimButton"
                @click="onClickEditClaim"
              >
                <font-awesome
                  icon="pen"
                  class="text-sm text-blue-500 ml-2 mb-1"
                />
              </button>
            </h2>
            <div class="flex justify-center w-full">
              <router-link
                v-if="veriClaim.id"
                :to="'/claim-cert/' + encodeURIComponent(veriClaim.id)"
                class="text-blue-500 mt-2"
                title="View Printable Certificate"
              >
                <font-awesome
                  icon="square"
                  class="text-white bg-yellow-500 p-1"
                />
              </router-link>
              <button
                v-if="veriClaim.id"
                class="text-blue-500 ml-2 mt-2"
                title="Copy Printable Certificate Link"
                @click="
                  copyToClipboard(
                    'A link to the certificate page',
                    `${APP_SERVER}/deep-link/claim-cert/${veriClaim.id}`,
                  )
                "
              >
                <font-awesome icon="link" class="text-yellow-500 p-1" />
              </button>
            </div>
            <!-- show link icon to copy this URL to the clipboard -->
            <div class="flex justify-end w-full">
              <button
                title="Copy Link"
                @click="copyToClipboard('A link to this page', windowDeepLink)"
              >
                <font-awesome icon="link" class="text-slate-500" />
              </button>
            </div>
          </div>
          <div class="text-sm">
            <div data-testId="description">
              <font-awesome icon="message" class="fa-fw text-slate-400" />
              {{
                (veriClaim.claim?.itemOffered as any)?.description ||
                (veriClaim.claim as any)?.description ||
                ""
              }}
            </div>
            <div>
              <font-awesome icon="user" class="fa-fw text-slate-400" />
              {{ didInfo(veriClaim.issuer) }}
            </div>
            <div>
              <font-awesome icon="calendar" class="fa-fw text-slate-400" />
              Recorded
              {{ veriClaim.issuedAt?.replace(/T/, " ").replace(/Z/, " UTC") }}
            </div>
            <div
              v-if="(veriClaim.claim as any).image"
              class="flex justify-center"
            >
              <a :href="(veriClaim.claim as any).image" target="_blank">
                <img
                  :src="(veriClaim.claim as any).image"
                  class="h-24 rounded-xl"
                />
              </a>
            </div>

            <div v-if="veriClaim.claimType === 'PlanAction'" class="mt-4">
              <router-link
                :to="'/project/' + encodeURIComponent(veriClaim.handleId)"
                class="text-blue-500 mt-2"
              >
                Go to Project page
              </router-link>
            </div>

            <!-- Fullfills Links -->

            <!-- fullfills links for a give -->
            <div v-if="detailsForGive?.fulfillsPlanHandleId" class="mt-4">
              <router-link
                :to="
                  '/project/' +
                  encodeURIComponent(detailsForGive?.fulfillsPlanHandleId)
                "
                class="text-blue-500 mt-2"
              >
                Fulfills a bigger plan...
              </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 -->
              <a
                class="text-blue-500 mt-4 cursor-pointer"
                @click="
                  showDifferentClaimPage(detailsForGive?.fulfillsHandleId)
                "
              >
                Fulfills
                {{
                  capitalizeAndInsertSpacesBeforeCaps(
                    detailsForGive.fulfillsType,
                  )
                }}...
              </a>
            </div>

            <!-- fullfills links for an offer -->
            <div v-if="detailsForOffer?.fulfillsPlanHandleId">
              <router-link
                :to="
                  '/project/' +
                  encodeURIComponent(detailsForOffer?.fulfillsPlanHandleId)
                "
                class="text-blue-500 mt-4"
              >
                Offered to a bigger plan...
              </router-link>
            </div>

            <!-- Providers -->
            <div v-if="providersForGive?.length > 0" class="mt-4">
              <span>Other assistance provided by:</span>
              <ul class="ml-4">
                <li
                  v-for="provider of providersForGive"
                  :key="provider.identifier"
                  class="list-disc ml-4"
                >
                  <div class="flex gap-4">
                    <div class="grow overflow-hidden">
                      <a
                        class="text-blue-500 mt-4 cursor-pointer"
                        @click="
                          provider.identifier.startsWith('did:')
                            ? $router.push(
                                '/did/' +
                                  encodeURIComponent(provider.identifier),
                              )
                            : showDifferentClaimPage(provider.identifier)
                        "
                      >
                        an activity...
                      </a>
                    </div>
                  </div>
                </li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="mt-2">
      <font-awesome icon="comment" class="text-slate-400" />
      {{ issuerName }} posted that.
    </div>
    <!--
    <div>
      <router-link :to="'/claim-cert/' + encodeURIComponent(veriClaim.id)">
        <font-awesome icon="file-contract" class="text-slate-400" />
        <span class="ml-2 text-blue-500">Printable Certificate</span>
      </router-link>
    </div>
    -->

    <div class="mt-8">
      <button
        v-if="libsUtil.canFulfillOffer(veriClaim, isRegistered)"
        class="col-span-1 block w-fit text-center text-md 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-1.5 py-2 rounded-md"
        @click="openFulfillGiftDialog()"
      >
        Affirm Delivery
        <font-awesome
          icon="hand-holding-heart"
          class="ml-2 text-white cursor-pointer"
        />
      </button>
    </div>
    <GiftedDialog ref="customGiveDialog" />

    <div v-if="libsUtil.isGiveAction(veriClaim)">
      <div class="flex columns-3">
        <button
          v-if="
            libsUtil.isGiveRecordTheUserCanConfirm(
              isRegistered,
              veriClaim,
              activeDid,
              confirmerIdList,
            )
          "
          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 mt-2 px-4 py-2 rounded-md"
          @click="confirmConfirmClaim()"
        >
          Confirm
          <font-awesome
            icon="circle-check"
            class="ml-2 text-white cursor-pointer"
          />
        </button>
        <h2 v-else class="font-bold uppercase text-xl mt-2">Confirmations</h2>

        <span class="mt-0.5 px-4 py-2">
          <router-link
            v-if="libsUtil.isGiveAction(veriClaim)"
            :to="'/confirm-gift/' + encodeURIComponent(veriClaim.id)"
            class="col-span-1 text-blue-500"
            data-testId="confirmGiftLink"
          >
            Details...
          </router-link>
        </span>
      </div>

      <div class="mt-2">
        <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>

      <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 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)">
                      <router-link
                        :to="{
                          path: '/did/' + encodeURIComponent(confirmerId),
                        }"
                        class="text-blue-500"
                      >
                        <font-awesome
                          icon="arrow-up-right-from-square"
                          class="fa-fw"
                        />
                      </router-link>
                    </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)">
                      <router-link
                        :to="{
                          path: '/did/' + encodeURIComponent(confsVisibleTo),
                        }"
                        class="text-blue-500"
                      >
                        <font-awesome
                          icon="arrow-up-right-from-square"
                          class="fa-fw"
                        />
                      </router-link>
                    </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>

    <!-- 
    Note that a similar section is found in ConfirmGiftView.vue, and kinda in HiddenDidDialog.vue
    -->
    <h2
      class="font-bold uppercase text-xl text-blue-500 mt-8 cursor-pointer"
      @click="showVeriClaimDump = !showVeriClaimDump"
    >
      Details
      <font-awesome v-if="showVeriClaimDump" icon="chevron-up" />
      <font-awesome v-else icon="chevron-right" />
    </h2>
    <div v-if="showVeriClaimDump">
      <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">
          You can ask one of your contacts to take a look and see if their
          contacts can see more details:
          <a class="text-blue-500" @click="onClickShareClaim()"
            >click to send them this page info</a
          >
          and see if they can make an introduction. Someone is connected to
          people closer to them; if you don't know who to ask, try the person
          who registered you.
        </span>
        <span v-else>
          You can ask one of your contacts to take a look and see if their
          contacts can see more details:
          <a
            class="text-blue-500"
            @click="copyToClipboard('A link to this page', windowDeepLink)"
            >click to copy this page info</a
          >
          and see if they can make an introduction. Someone is connected to
          people closer to them; if you don't know who to ask, try the person
          who registered you.
        </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 class="text-blue-500" @click="onClickShareClaim()"
            >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
            class="text-blue-500"
            @click="copyToClipboard('A link to this page', windowDeepLink)"
            >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">
            <font-awesome 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)">
                      <router-link
                        :to="{
                          path: '/did/' + encodeURIComponent(visDid),
                        }"
                        class="text-blue-500"
                      >
                        <font-awesome
                          icon="arrow-up-right-from-square"
                          class="fa-fw"
                        />
                      </router-link>
                    </span>
                    <span v-if="veriClaim.publicUrls?.[visDid]"
                      >, found at&nbsp;<a
                        :href="veriClaim.publicUrls?.[visDid]"
                        target="_blank"
                        class="text-blue-500"
                      >
                        <font-awesome icon="globe" class="fa-fw" />
                        {{
                          veriClaim.publicUrls[visDid].substring(
                            veriClaim.publicUrls[visDid].indexOf("//") + 2,
                          )
                        }}
                      </a>
                    </span>
                  </span>
                </div>
              </li>
            </ul>
          </div>
        </div>
      </div>
      <span v-if="isEditedGlobalId" class="mt-2">
        This record is an edited version. The latest version is shown.
      </span>
      <br />
      <!-- Keep the dump contents directly between > and < to avoid weird spacing. -->
      <pre
        v-if="showVeriClaimDump"
        class="text-sm overflow-x-scroll bg-slate-100 px-4 py-3 rounded-md"
        >{{ veriClaimDump }}</pre
      >

      <h2 class="text-xl mt-8 mb-2">Full Claim</h2>
      <p class="mb-4">
        The full claim includes the claim as it was originally issued, including
        the signature (ie. the proof of issuance by that person).
      </p>
      <div v-if="!fullClaim">
        <p v-if="fullClaimMessage" class="mb-4">
          {{ fullClaimMessage }}
        </p>
        <button
          v-else
          class="text-blue-500 cursor-pointer"
          @click="showFullClaim(veriClaim.id as string)"
        >
          <font-awesome icon="file-lines" class="fa-fw" />
          Load Full Claim Details
        </button>
      </div>
      <div v-else>
        <pre
          class="text-sm overflow-x-scroll bg-slate-100 px-4 py-3 rounded-md"
          >{{ fullClaimDump }}</pre
        >
      </div>

      <a
        :href="apiServer + '/api/claim/' + veriClaim.id"
        target="_blank"
        class="text-blue-500 cursor-pointer"
      >
        <font-awesome icon="file-lines" class="fa-fw" />
        <font-awesome icon="arrow-up-right-from-square" class="ml-1 fa-fw" />
        View on the Public Server
      </a>
    </div>
  </section>
</template>

<script lang="ts">
import { AxiosError } from "axios";
import * as yaml from "js-yaml";
import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator";
import { Router, RouteLocationNormalizedLoaded } from "vue-router";
import { useClipboard } from "@vueuse/core";
import { GenericVerifiableCredential } from "../interfaces";
import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts";
import * as serverUtil from "../libs/endorserServer";
import { GenericCredWrapper, OfferClaim, ProviderInfo } from "../interfaces";
import * as libsUtil from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";

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

  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: {
    fulfillsPlanHandleId?: string;
    fulfillsType?: string;
    fulfillsHandleId?: string;
  } | null = null;
  detailsForOffer: { fulfillsPlanHandleId?: string } | null = null;
  fullClaim = null;
  fullClaimDump = "";
  fullClaimMessage = "";
  isEditedGlobalId = false;
  isRegistered = false;
  issuerName = "";
  numConfsNotVisible = 0; // number of hidden DIDs in the confirmerIdList, minus the issuer if they aren't visible
  providersForGive: ProviderInfo[] = [];
  showIdCopy = false;
  showVeriClaimDump = false;
  veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
  veriClaimDump = "";
  veriClaimDidsVisible: { [key: string]: string[] } = {};
  windowDeepLink = window.location.href; // changed in the setup for deep linking

  APP_SERVER = APP_SERVER;
  R = R;
  yaml = yaml;
  libsUtil = libsUtil;
  serverUtil = serverUtil;
  window = window;

  resetThisValues() {
    this.confirmerIdList = [];
    this.confsVisibleErrorMessage = "";
    this.confsVisibleToIdList = [];
    this.detailsForGive = null;
    this.detailsForOffer = null;
    this.fullClaim = null;
    this.fullClaimDump = "";
    this.fullClaimMessage = "";
    this.isEditedGlobalId = false;
    this.numConfsNotVisible = 0;
    this.providersForGive = [];
    this.veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
    this.veriClaimDump = "";
    this.veriClaimDidsVisible = {};
  }

  async created() {
    let settings = await databaseUtil.retrieveSettingsForActiveAccount();
    if (USE_DEXIE_DB) {
      settings = await databaseUtil.retrieveSettingsForActiveAccount();
    }

    this.activeDid = settings.activeDid || "";
    this.apiServer = settings.apiServer || "";
    const platformService = PlatformServiceFactory.getInstance();
    const dbAllContacts = await platformService.dbQuery(
      "SELECT * FROM contacts",
    );
    this.allContacts = databaseUtil.mapQueryResultToValues(
      dbAllContacts,
    ) as unknown as Contact[];
    if (USE_DEXIE_DB) {
      await db.open();
      this.allContacts = await db.contacts.toArray();
    }
    this.isRegistered = settings.isRegistered || false;

    try {
      this.allMyDids = await libsUtil.retrieveAccountDids();
    } catch (error) {
      logConsoleAndDb(
        "Error retrieving all account DIDs on home page:" + error,
        true,
      );
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error Loading Profile",
          text: "See the Help page for problems with your personal data.",
        },
        5000,
      );
    }

    const claimId = this.$route.params.id as string;
    if (claimId) {
      await this.loadClaim(claimId, this.activeDid);
    } else {
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "No claim ID was provided.",
        },
        5000,
      );
    }
    this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;

    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");
  }

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

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

  async loadClaim(claimId: string, userDid: string) {
    const urlPath = libsUtil.isGlobalUri(claimId)
      ? "/api/claim/byHandle/"
      : "/api/claim/";
    const url = this.apiServer + urlPath + encodeURIComponent(claimId);
    const headers = await serverUtil.getHeaders(userDid);

    try {
      const resp = await this.axios.get(url, { headers });
      if (resp.status === 200) {
        this.veriClaim = resp.data;
        this.issuerName = this.didInfo(this.veriClaim.issuer);
        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
        logger.error("Error getting claim:", resp);
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "There was a problem retrieving that claim.",
          },
          5000,
        );
        return;
      }

      this.isEditedGlobalId = !this.veriClaim.handleId.endsWith(claimId);

      // retrieve more details on Give, Offer, or Plan
      if (this.veriClaim.claimType === "GiveAction") {
        const giveUrl =
          this.apiServer +
          "/api/v2/report/gives?handleId=" +
          encodeURIComponent(this.veriClaim.handleId as string);
        const giveHeaders = await serverUtil.getHeaders(userDid);
        const giveResp = await this.axios.get(giveUrl, {
          headers: giveHeaders,
        });
        if (giveResp.status === 200 && giveResp.data.data?.length > 0) {
          this.detailsForGive = giveResp.data.data[0];
        } else {
          logger.error("Error getting detailed give info:", giveResp);
        }

        // look for providers
        const providerUrl =
          this.apiServer +
          "/api/v2/report/providersToGive?handleId=" +
          encodeURIComponent(this.veriClaim.handleId as string);
        const providerHeaders = await serverUtil.getHeaders(userDid);
        const providerResp = await this.axios.get(providerUrl, {
          headers: providerHeaders,
        });
        // should be at least an empty array
        if (
          providerResp.status === 200 &&
          Array.isArray(providerResp.data.data)
        ) {
          this.providersForGive = providerResp.data.data;
        } else {
          logger.error("Error getting give providers:", giveResp);
          this.$notify(
            {
              group: "alert",
              type: "warning",
              title: "Error",
              text: "Got error retrieving linked provider data.",
            },
            5000,
          );
        }
      } else if (this.veriClaim.claimType === "Offer") {
        const offerUrl =
          this.apiServer +
          "/api/v2/report/offers?handleId=" +
          encodeURIComponent(this.veriClaim.handleId as string);
        const offerHeaders = await serverUtil.getHeaders(userDid);
        const offerResp = await this.axios.get(offerUrl, {
          headers: offerHeaders,
        });
        if (offerResp.status === 200) {
          this.detailsForOffer = offerResp.data.data[0];
        } else {
          logger.error("Error getting detailed offer info:", offerResp);
          this.$notify(
            {
              group: "alert",
              type: "warning",
              title: "Error",
              text: "Got error retrieving linked offer data.",
            },
            5000,
          );
        }
      }

      // retrieve the list of confirmers
      const confirmerInfo = await libsUtil.retrieveConfirmerIdList(
        this.apiServer,
        claimId,
        this.veriClaim.issuer,
        userDid,
      );
      if (confirmerInfo) {
        this.confirmerIdList = confirmerInfo.confirmerIdList;
        this.confsVisibleToIdList = confirmerInfo.confsVisibleToIdList;
        this.numConfsNotVisible = confirmerInfo.numConfsNotVisible;
      } else {
        this.confsVisibleErrorMessage =
          "Had problems retrieving confirmations.";
      }
    } catch (error: unknown) {
      const serverError = error as AxiosError;
      logger.error("Error retrieving claim:", serverError);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "Something went wrong retrieving claim data.",
        },
        3000,
      );
    }
  }

  async showFullClaim(claimId: string) {
    const url =
      this.apiServer + "/api/claim/full/" + encodeURIComponent(claimId);
    const headers = await serverUtil.getHeaders(this.activeDid);

    try {
      const resp = await this.axios.get(url, { headers });
      if (resp.status === 200) {
        this.fullClaim = resp.data;
        this.fullClaimDump = yaml.dump(this.fullClaim);
      } else {
        // actually, axios typically throws an error so we never get here
        logger.error("Error getting full claim:", resp);
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "There was a problem getting that claim.",
          },
          5000,
        );
      }
    } catch (error: unknown) {
      logger.error("Error retrieving full claim:", error);
      const serverError = error as AxiosError;
      if (serverError.response?.status === 403) {
        let issuerPhrase = "";
        const issuerContact = serverUtil.contactForDid(
          this.veriClaim.issuer,
          this.allContacts,
        );
        if (issuerContact?.name) {
          issuerPhrase +=
            "Ask " +
            issuerContact.name +
            " to show you the full claim details.";
        }
        if (
          this.confirmerIdList.length > 0 ||
          this.confsVisibleToIdList.length > 0
        ) {
          if (issuerContact?.name) {
            issuerPhrase +=
              "You could also ask someone in the Confirmations section to make an introduction.";
          } else {
            issuerPhrase +=
              "Ask someone in the Confirmations section to make an introduction.";
          }
        }
        this.fullClaimMessage =
          "You are not authorized to view the full contents of this claim." +
          issuerPhrase +
          " You might ask someone in your network -- like the person who registered you --" +
          " if they can find out more and make an introduction: " +
          " send them this page and see if they can make a connection for you.";
      } else {
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text: "Something went wrong retrieving that claim.",
          },
          5000,
        );
      }
    }
  }

  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: GenericVerifiableCredential = {
      "@context": "https://schema.org",
      "@type": "AgreeAction",
      object: goodClaim,
    };
    const result = await serverUtil.createAndSubmitClaim(
      confirmationClaim,
      this.activeDid,
      this.apiServer,
      this.axios,
    );
    if (result.success) {
      this.$notify(
        {
          group: "alert",
          type: "success",
          title: "Success",
          text: "Confirmation submitted.",
        },
        5000,
      );
    } else {
      logger.error("Got error submitting the confirmation:", result);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "There was a problem submitting the confirmation.",
        },
        5000,
      );
    }
  }

  showDifferentClaimPage(claimId: string) {
    const route = {
      path: "/claim/" + encodeURIComponent(claimId),
    };
    (this.$router as Router).push(route).then(async () => {
      this.resetThisValues();
      await this.loadClaim(claimId, this.activeDid);
    });
  }

  openFulfillGiftDialog() {
    const giver: libsUtil.GiverReceiverInputInfo = {
      did: libsUtil.offerGiverDid(
        this.veriClaim as GenericCredWrapper<OfferClaim>,
      ),
    };
    (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,
        );
      });
  }

  onClickShareClaim() {
    this.copyToClipboard("A link to this page", this.windowDeepLink);
    window.navigator.share({
      title: "Help Connect Me",
      text: "I'm trying to find the people who recorded this. Can you help me?",
      url: this.windowDeepLink,
    });
  }

  onClickEditClaim() {
    if (this.veriClaim.claimType === "GiveAction") {
      const route = {
        name: "gifted-details",
        query: {
          prevCredToEdit: JSON.stringify(this.veriClaim),
          destinationPathAfter:
            "/claim/" + encodeURIComponent(this.veriClaim.handleId),
        },
      };
      (this.$router as Router).push(route);
    } else if (this.veriClaim.claimType === "Offer") {
      const route = {
        name: "offer-details",
        query: {
          prevCredToEdit: JSON.stringify(this.veriClaim),
          destinationPathAfter:
            "/claim/" + encodeURIComponent(this.veriClaim.handleId),
        },
      };
      (this.$router as Router).push(route);
    } else if (this.veriClaim.claimType === "PlanAction") {
      const route = {
        name: "new-edit-project",
        query: { projectId: this.veriClaim.handleId },
      };
      (this.$router as Router).push(route);
    } else {
      logger.error(
        "Unrecognized claim type for edit:",
        this.veriClaim.claimType,
      );
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "This is an unrecognized claim type.",
        },
        3000,
      );
    }
  }
}
</script>
<style>
/*
  Tooltip, generated on "title" attributes on "fa" icons
  Kudos to https://www.w3schools.com/css/css_tooltip.asp
*/
/* Tooltip container */
.tooltip {
  position: relative;
  display: inline-block;
  border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}

/* Tooltip text */
.tooltip .tooltiptext {
  visibility: hidden;
  width: 200px;
  background-color: black;
  color: #fff;
  text-align: center;
  padding: 5px 0;
  border-radius: 6px;

  position: absolute;
  z-index: 1;
}

/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
  visibility: visible;
}
.tooltip:hover .tooltiptext-left {
  visibility: visible;
}
</style>
