<template>
  <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">
        <!-- Cancel -->
        <button
          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
          @click="$router.go(-1)"
        >
          <font-awesome icon="chevron-left"></font-awesome>
        </button>
        Derive from Existing Identity
      </h1>
    </div>
    <!-- Import Account Form -->

    <div>
      <p class="text-center text-xl mb-4 font-light">
        Will increment the maximum known derivation path from the existing seed.
      </p>

      <p v-if="Object.keys(didArrays).length > 1">
        Choose existing DIDs from same seed phrase to compute derivation.
      </p>
      <ul class="mb-4">
        <li
          v-for="dids in Object.values(didArrays)"
          :key="dids[0].did"
          class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-2"
          @click="switchAccount(dids[0].did)"
        >
          <font-awesome
            v-if="dids[0].did == selectedArrayFirstDid"
            icon="circle"
            class="fa-fw text-blue-500 text-xl mr-3"
          ></font-awesome>
          <font-awesome
            v-else
            icon="circle"
            class="fa-fw text-slate-400 text-xl mr-3"
          ></font-awesome>
          <span class="overflow-hidden">
            <div class="text-sm text-slate-500">
              <code>{{ dids.map((d) => d.did).join(" ") }}</code>
            </div>
          </span>
        </li>
      </ul>
    </div>
    <div class="mt-8">
      <div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
        <button
          class="block w-full text-center text-lg font-bold uppercase 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-2 py-3 rounded-md"
          @click="incrementDerivation()"
        >
          Increment and Import
        </button>
        <button
          type="button"
          class="block w-full text-center text-md uppercase 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-1.5 py-2 rounded-md"
          @click="onCancelClick()"
        >
          Cancel
        </button>
      </div>
    </div>
  </section>
</template>

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

import {
  DEFAULT_ROOT_DERIVATION_PATH,
  deriveAddress,
  newIdentifier,
  nextDerivationPath,
} from "../libs/crypto";
import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import {
  retrieveAllAccountsMetadata,
  retrieveFullyDecryptedAccount,
  saveNewIdentity,
} from "../libs/util";
import { logger } from "../utils/logger";
import { Account, AccountEncrypted } from "../db/tables/accounts";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { USE_DEXIE_DB } from "@/constants/app";

@Component({
  components: {},
})
export default class ImportAccountView extends Vue {
  $route!: RouteLocationNormalizedLoaded;
  $router!: Router;

  derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
  didArrays: Record<string, Account[]> = {};
  selectedArrayFirstDid = "";

  async mounted() {
    const accounts: AccountEncrypted[] = await retrieveAllAccountsMetadata();
    const decryptedAccounts: (Account | undefined)[] = await Promise.all(
      accounts.map(async (account) => {
        return retrieveFullyDecryptedAccount(account.did);
      }),
    );
    const filteredDecryptedAccounts: Account[] = decryptedAccounts.filter(
      (account) => account !== undefined,
    );

    // group by account.mnemonic
    const groupedAccounts: Record<string, Account[]> = R.groupBy(
      (a) => a.mnemonic || "",
      filteredDecryptedAccounts,
    ) as Record<string, Account[]>;

    this.didArrays = groupedAccounts;
    if (Object.keys(this.didArrays).length > 0) {
      this.selectedArrayFirstDid = Object.values(this.didArrays)[0][0].did;
    }
  }

  public onCancelClick() {
    this.$router.back();
  }

  public switchAccount(did: string) {
    this.selectedArrayFirstDid = did;
  }

  public async incrementDerivation() {
    // find the maximum derivation path for the selected DIDs
    const selectedArray: Array<Account> =
      Object.values(this.didArrays).find(
        (dids) => dids[0].did === this.selectedArrayFirstDid,
      ) || [];
    // extract the derivationPath array and sort it
    const derivationPaths = selectedArray.map(
      (account) => account.derivationPath,
    );
    derivationPaths.sort((a, b) => {
      const aParts = a?.split("/");
      const aLast = aParts?.[aParts.length - 1];
      const bParts = b?.split("/");
      const bLast = bParts?.[bParts.length - 1];
      return parseInt(aLast || "0") - parseInt(bLast || "0");
    });
    // we're sure there's at least one
    const maxDerivPath: string = derivationPaths[
      derivationPaths.length - 1
    ] as string;

    const newDerivPath = nextDerivationPath(maxDerivPath);

    const mne = selectedArray[0].mnemonic as string;
    const [address, privateHex, publicHex] = deriveAddress(mne, newDerivPath);

    const newId = newIdentifier(address, publicHex, privateHex, newDerivPath);

    try {
      await saveNewIdentity(newId, mne, newDerivPath);

      // record that as the active DID
      const platformService = PlatformServiceFactory.getInstance();
      await platformService.dbExec("UPDATE settings SET activeDid = ?", [
        newId.did,
      ]);
      await databaseUtil.updateDidSpecificSettings(newId.did, {
        isRegistered: false,
      });
      if (USE_DEXIE_DB) {
        await db.settings.update(MASTER_SETTINGS_KEY, {
          activeDid: newId.did,
        });
      }
      this.$router.push({ name: "account" });
    } catch (err) {
      logger.error("Error saving mnemonic & updating settings:", err);
    }
  }
}
</script>
