<!--
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-->

<!--
  @component  
  "Account Info" user panel sub menu.
  Provides info about wallet, broker, etc. and download option.
-->

<script lang="ts">
  import { link, push } from "svelte-spa-router";
  import CenteredLayout from "../lib/CenteredLayout.svelte";
  import { ArrowLeft, ServerStack } from "svelte-heros-v2";
  import { onMount, tick } from "svelte";
  import { Sidebar, SidebarGroup, SidebarWrapper } from "flowbite-svelte";

  import { active_session, active_wallet, connections } from "../store";

  import { default as ng } from "../api";
  import DeviceIcon from "../lib/components/DeviceIcon.svelte";

  let error;
  let nonActiveClass =
    "flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700";

  let top;

  async function scrollToTop() {
    await tick();
    top.scrollIntoView();
  }
  onMount(async () => {
    if (!$active_session) {
      push("#/");
    } else {
      await scrollToTop();
    }
  });

  $: wallet_unlocked = $active_wallet?.wallet?.V0;

  $: personal_site_id = wallet_unlocked?.personal_site_id;

  /**
   * brokers:
      ZBY5Y8DTyhMo5xfo5K4FCsJHVaN3O15vKeQBwZxr76YA: [
         ServerV0:
          can_forward: true
          can_verify: false
          peer_id: Object { Ed25519PubKey: (32) […] }
          server_type: Object {
            Domain
            Localhost: 1440 // if domain not exist
            BoxPrivate  // one IPv4 and optionally one IPv6 to connect to an NGbox on private LAN rs type Vec<BindAddress>
            Public  // one IPv4 and optionally one IPv6 to connect to an NGbox on public (edge) internet. rs type Vec<BindAddress>
            BoxPublicDyn  // same but with dynamic IPs that can be retrieved with a special API. rs type Vec<BindAddress>
            }
      ]
   */

  /*
   * Connections Is a record of string to those objects:
    error: undefined​​
    server_id: "ZBY5Y8DTyhMo5xfo5K4FCsJHVaN3O15vKeQBwZxr76YA"
    server_ip: "ws://localhost:1440"
    since: Date Fri Jul 05 2024 09:46:30 GMT+0200 (Central European Summer Time)
  */
  // let connections;

  /**
   * bootstraps: Array [ {…} ]
   * cores: Array [ (2) […] ]
   * id: Object { Ed25519PubKey: (32) […] }
   * name: "Personal"
   * private: Object { id: {…}, store_type: "Private" }
   * protected: Object { id: {…}, store_type: "Protected" }
   * public: Object { id: {…}, store_type: "Public" }
   * site_type: Object { Individual: (2) […] } // Some key data as well
   */
  $: walletSites = wallet_unlocked?.sites;

  /** Type:
   * client_type: "Web"
   * details: '{"browser":{"name":"Firefox","version":"127.0","appVersion":"5.0 (X11)","arch":"Linux x86_64","vendor":"","ua":"Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"},"os":{"name":"Linux"},"platform":{"type":"desktop"},"engine":{"name":"Gecko","version":"20100101","sdk":"0.1.0-preview.1"}}'
   * timestamp_install: 0
   * timestamp_updated: 0
   * version: "0.1.0"
   */
  var device_info;

  $: display_sites = Object.entries(walletSites || {})
    ?.map(([user_id, site]) => {
      // Try to extract device details (for now only of the connected device).
      // TODO: API for all devices
      const devices = (!device_info ? [] : [device_info.V0]).map((device) => {
        const device_details = JSON.parse(device.details);
        return {
          name: device.name, // TODO: API device.name is not provided
          peer_id: device.id, // TODO: API device id is is not provided
          version: device.version,
          details: device_details,
          device_name:
            device.client_type === "web"
              ? `${device_details?.browser?.name}${" - " + device_details?.browser.arch || ""}`
              : `${device_details?.os?.name_uname || device_details?.os?.name_rust || device_details?.os?.name} - ${device_details?.os?.version_uname || device_details?.os?.version_rust}`,
          type: device.client_type,
        };
      });

      return {
        id: user_id,
        connection: $connections[user_id], // error, server_id, server_ip, since
        devices,
        // @ts-ignore
        name: site.name,
      };
    })
    .filter((site) => site.id === personal_site_id);

  $: display_brokers = Object.entries(wallet_unlocked?.brokers || {}).map(
    // @ts-ignore
    ([broker_id, [broker]]) => {
      //TODO: there can be several broker definitions for the same broker_id (if the broker can be reached by different means)
      return {
        id: broker_id,
        can_forward: broker.ServerV0.can_forward,
        can_verify: broker.ServerV0.can_verify,
        address:
          broker.ServerV0.server_type.Domain ||
          `localhost:${broker.ServerV0.server_type.Localhost}`,
        last_connected: new Date("1970-01-01T00:00:00Z").toLocaleString(), // TODO: API
      };
    }
  );

  // $: console.info(JSON.stringify(device_info));

  // $: console.debug(
  //   "info",
  //   device_info,
  //   "walletSites",
  //   walletSites,
  //   "wallet",
  //   $active_wallet,
  //   "connections",
  //   $connections,
  //   "display_brokers",
  //   display_brokers,
  //   "display_sites",
  //   display_sites
  // );

  onMount(async () => {
    ng.client_info().then((res) => {
      device_info = res;
    });
  });
</script>

<CenteredLayout>
  <div class="container3" bind:this={top}>
    <div class="row mb-20">
      <Sidebar {nonActiveClass}>
        <SidebarWrapper
          divClass="bg-gray-60 overflow-y-auto py-4 px-3 rounded dark:bg-gray-800"
        >
          <!-- Go Back-->
          <SidebarGroup ulClass="space-y-2" role="menu">
            <li>
              <h2 class="text-xl mb-6">Account Info</h2>
            </li>
            <li
              tabindex="0"
              role="menuitem"
              class="flex items-center p-2 text-base font-normal text-gray-900 clickable rounded-lg dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700"
              on:keypress={() => window.history.go(-1)}
              on:click={() => window.history.go(-1)}
            >
              <ArrowLeft
                tabindex="-1"
                class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
              />
              <span class="ml-3">Back</span>
            </li>
          </SidebarGroup>

          <!-- For now this will only consist of the `Personal` one-->
          {#each display_sites as site}
            <li
              class="flex items-center p-2 text-base font-normal text-gray-900"
            >
              <h3 class="flex items-center mt-2 text-lg font-normal">
                {site.name} account
              </h3>
            </li>

            <!-- Device Details -->
            <SidebarGroup ulClass="space-y-1">
              <li
                class="flex items-center p-2 text-base font-normal text-gray-900"
              >
                <h4
                  class="flex items-center mt-2 text-base font-normal text-gray-600"
                >
                  Devices
                </h4>
              </li>
              {#each site.devices as device, index}
                <li
                  class="flex items-center p-2 text-base font-normal text-gray-900 bg-white shadow-md rounded-lg"
                  class:border-b={index !== site.devices.length - 1}
                >
                  <div>
                    <DeviceIcon device={device.type} />
                  </div>
                  <div
                    class="flex flex-col ml-3 items-start text-left overflow-auto"
                  >
                    <div>
                      <span class="text-gray-500">Name</span>
                      <span class="break-all">{device.name}</span>
                    </div>
                    <div>
                      <span class="text-gray-500">ID</span>
                      <span class="break-all">{device.peer_id}</span>
                    </div>
                    <div>
                      <span class="text-gray-500">Version</span>
                      <span>{device.version}</span>
                    </div>
                    <div>
                      <span class="text-gray-500">System</span>
                      <span> {device.device_name}</span>
                    </div>
                  </div>
                </li>
              {/each}
            </SidebarGroup>

            <!-- Broker Details -->
            <SidebarGroup ulClass="space-y-1">
              <li
                class="flex items-center p-2 text-base font-normal text-gray-900"
              >
                <h4
                  class="flex items-center mt-2 text-base font-normal text-gray-600"
                >
                  Brokers
                </h4>
              </li>

              {#if display_brokers.length > 0}
                {#each Object.values(display_brokers) as broker, index}
                  <!--
                         (peerId, IP/port or domain, last time connected)
                        -->
                  <li
                    class="flex items-center p-2 text-base font-normal text-gray-900 bg-white shadow-md rounded-lg"
                    class:border-b={index !== display_brokers.length - 1}
                  >
                    <div>
                      <ServerStack
                        tabindex="-1"
                        class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
                      />
                    </div>

                    <div class="flex flex-col ml-3 items-start text-left">
                      <div>
                        <span class="text-gray-500">Address</span><br />
                        <span class="break-all">{broker.address}</span>
                      </div>
                      <div>
                        <span class="text-gray-500">Last Connected</span><br />
                        <span class="break-all">{broker.last_connected}</span>
                      </div>
                      <div>
                        <span class="text-gray-500">ID</span>
                        <span class="break-all">{broker.id}</span>
                      </div>
                      <!-- <div>
                        <span class="text-gray-500">Can Forward?</span>
                        <span>{broker.can_forward}</span>
                      </div>
                      <div>
                        <span class="text-gray-500">Can Verify?</span>
                        <span>{broker.can_verify}</span>
                      </div> -->
                    </div>
                  </li>
                {/each}
              {:else}
                <li
                  class="flex items-center p-2 text-base font-normal text-gray-900"
                >
                  <span class="ml-3">No brokers connected</span>
                </li>
              {/if}
            </SidebarGroup>
          {/each}
        </SidebarWrapper>
      </Sidebar>
    </div>
    {#if error}
      <div class=" max-w-6xl lg:px-8 mx-auto px-4 text-red-800">
        <svg
          class="animate-bounce mt-10 h-16 w-16 mx-auto"
          fill="none"
          stroke="currentColor"
          stroke-width="1.5"
          viewBox="0 0 24 24"
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
        >
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
          />
        </svg>
        {#if error == "AlreadyExists"}
          <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5">
            The user is already registered with the selected broker.<br /> Try logging
            in instead
          </p>
          <a use:link href="/">
            <button
              tabindex="-1"
              class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
            >
              Login
            </button>
          </a>
        {:else}
          <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-5">
            An error occurred:<br />{error}
          </p>
          <a use:link href="/">
            <button
              tabindex="-1"
              class="text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
            >
              Go back to homepage
            </button>
          </a>
        {/if}
      </div>
    {/if}
  </div>
</CenteredLayout>

<style>
  li.clickable {
    cursor: pointer;
  }
</style>
