<template>
  <QuickNav selected="Contacts"></QuickNav>
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Back -->
    <div class="text-lg text-center font-light relative px-7">
      <h1
        class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
        @click="$router.back()"
      >
        <fa icon="chevron-left" class="fa-fw"></fa>
      </h1>
    </div>

    <!-- Heading -->
    <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
      Contact Import
    </h1>

    <span>
      Note that you will have to make them visible one-by-one in the list of
      Contacts.
    </span>
    <div v-if="sameCount > 0">
      {{ sameCount }} contact{{ sameCount == 1 ? "" : "s" }} are the same as
      existing contacts.
    </div>

    <!-- Results List -->
    <ul v-if="contactsImporting.length > 0" class="border-t border-slate-300">
      <li v-for="(contact, index) in contactsImporting" :key="contact.did">
        <div
          v-if="
            !contactsExisting[contact.did] ||
            !R.isEmpty(contactDifferences[contact.did])
          "
          class="grow overflow-hidden border-b border-slate-300 pt-2.5 pb-4"
        >
          <h2 class="text-base font-semibold">
            <input type="checkbox" v-model="contactsSelected[index]" />
            {{ contact.name || AppString.NO_CONTACT_NAME }}
            -
            <span v-if="contactsExisting[contact.did]" class="text-orange-500"
              >Existing</span
            >
            <span v-else class="text-green-500">New</span>
          </h2>
          <div class="text-sm truncate">
            {{ contact.did }}
          </div>
          <div v-if="contactDifferences[contact.did]">
            <div>
              <div class="grid grid-cols-3 gap-2">
                <div class="font-bold">Field</div>
                <div class="font-bold">Old Value</div>
                <div class="font-bold">New Value</div>
              </div>
              <div
                v-for="(value, contactField) in contactDifferences[contact.did]"
                :key="contactField"
                class="grid grid-cols-3 border"
              >
                <div class="border p-1">{{ contactField }}</div>
                <div class="border p-1">{{ value.old }}</div>
                <div class="border p-1">{{ value.new }}</div>
              </div>
            </div>
          </div>
        </div>
      </li>
      <fa icon="spinner" v-if="importing" class="animate-spin" />
      <button
        v-else
        class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-sm text-white mt-2 px-2 py-1.5 rounded"
        @click="importContacts"
      >
        Import Selected Contacts
      </button>
    </ul>
    <p v-else>There are no contacts to import.</p>
  </section>
</template>

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

import { AppString, NotificationIface } from "@/constants/app";
import { db } from "@/db/index";
import { Contact } from "@/db/tables/contacts";
import * as libsUtil from "@/libs/util";
import QuickNav from "@/components/QuickNav.vue";
import EntityIcon from "@/components/EntityIcon.vue";
import OfferDialog from "@/components/OfferDialog.vue";

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

  AppString = AppString;
  libsUtil = libsUtil;
  R = R;

  contactsExisting: Record<string, Contact> = {}; // user's contacts already in the system, keyed by DID
  contactsImporting: Array<Contact> = []; // contacts from the import
  contactsSelected: Array<boolean> = []; // whether each contact in contactsImporting is selected
  contactDifferences: Record<
    string,
    Record<string, { new: string; old: string }>
  > = {}; // for existing contacts, it shows the difference between imported and existing contacts for each key
  importing = false;
  sameCount = 0;

  async created() {
    // Retrieve the imported contacts from the query parameter
    const importedContacts =
      ((this.$route as Router).query["contacts"] as string) || "[]";
    this.contactsImporting = JSON.parse(importedContacts);
    this.contactsSelected = new Array(this.contactsImporting.length).fill(
      false,
    );

    await db.open();
    const baseContacts = await db.contacts.toArray();
    // set the existing contacts, keyed by DID, if they exist in contactsImporting
    for (let i = 0; i < this.contactsImporting.length; i++) {
      const contactIn = this.contactsImporting[i];
      const existingContact = baseContacts.find(
        (contact) => contact.did === contactIn.did,
      );
      if (existingContact) {
        this.contactsExisting[contactIn.did] = existingContact;

        const differences: Record<string, { new: string; old: string }> = {};
        Object.keys(contactIn).forEach((key) => {
          if (contactIn[key] !== existingContact[key]) {
            differences[key] = {
              old: existingContact[key],
              new: contactIn[key],
            };
          }
        });
        this.contactDifferences[contactIn.did] = differences;
        if (R.isEmpty(differences)) {
          this.sameCount++;
        }
      } else {
        // automatically import new data
        this.contactsSelected[i] = true;
      }
    }
  }

  async importContacts() {
    this.importing = true;
    let importedCount = 0,
      updatedCount = 0;
    for (let i = 0; i < this.contactsImporting.length; i++) {
      if (this.contactsSelected[i]) {
        const contact = this.contactsImporting[i];
        const existingContact = this.contactsExisting[contact.did];
        if (existingContact) {
          await db.contacts.update(contact.did, contact);
          updatedCount++;
        } else {
          // without explicit clone on the Proxy, we get: DataCloneError: Failed to execute 'add' on 'IDBObjectStore': #<Object> could not be cloned.
          await db.contacts.add(R.clone(contact));
          importedCount++;
        }
      }
    }
    this.importing = false;

    this.$notify(
      {
        group: "alert",
        type: "success",
        title: "Import Success",
        text:
          `${importedCount} contact${importedCount == 1 ? "" : "s"} imported.` +
          (updatedCount ? ` ${updatedCount} updated.` : ""),
      },
      3000,
    );
    (this.$router as Router).push({ name: "contacts" });
  }
}
</script>
