<script lang="ts">
  import { fetchEntry, query as queryFn } from "../lib/entity";
  import debounce from "lodash/debounce";
  import { Readable, readable } from "svelte/store";
  import type { UpEntry, UpListing, UpObject } from "upend";
  import Spinner from "../components/utils/Spinner.svelte";
  import UpEntryDisplay from "../components/display/UpEntry.svelte";
  import UpObjectDisplay from "../components/display/UpObject.svelte";
  import UpObjectCard from "../components/display/UpObjectCard.svelte";
  export let query: string;

  let debouncedQuery = "";
  const updateQuery = debounce((query: string) => {
    debouncedQuery = query;
  }, 200);
  $: updateQuery(query);

  let result: Readable<UpListing> = readable();
  let error: Readable<unknown> = readable();
  $: if (debouncedQuery.length) {
    ({ result, error } = queryFn(
      () => `(matches ? ? (contains "${debouncedQuery}"))`
    ));
  }

  $: entries = ($result?.entries || []).sort((a, b) =>
    a.address.localeCompare(b.address)
  );

  async function getObjects(entries: UpEntry[]): Promise<string[]> {
    exactHits.length = 0;
    const labelled = entries
      .filter((e) => e.attribute == "LBL")
      .map((e) => e.entity);
    const aliased = entries
      .filter((e) => e.attribute === "ALIAS")
      .map(async (e) => {
        const entry = await fetchEntry(e.entity);
        return String(entry.value.c);
      });
    return labelled.concat(await Promise.all(aliased));
  }

  $: objects = getObjects($result?.entries || []);
  let exactHits = [];

  function onResolved(address: string, ids: string[]) {
    console.log({ address, ids });

    if (ids.some((id) => id.toLowerCase() === query.toLowerCase())) {
      if (!exactHits.includes(address)) {
        exactHits.push(address);
        exactHits = exactHits;
      }
    }
  }
</script>

<div>
  {#if !$error}
    {#if $result}
      <section class="exact">
        <h2>Exact</h2>
        {#if exactHits.length}
          <ul>
            {#each exactHits as address}
              <li>
                <UpObjectCard {address} --width="100%" --height="100%" />
              </li>
            {/each}
          </ul>
        {:else}
          <div class="create">Create?</div>
          <div class="create" />
        {/if}
      </section>

      <section class="objects">
        <h2>Objects</h2>
        {#await objects}
          <Spinner />
        {:then objects}
          <ul>
            {#each objects as address}
              <li>
                <UpObjectDisplay
                  {address}
                  on:resolved={(ids) => onResolved(address, ids.detail)}
                />
              </li>
            {/each}
          </ul>
        {/await}
      </section>

      {#if entries.length}
        <section class="raw">
          <h2>Raw results</h2>
          <ul>
            {#each entries as entry}
              <li><UpEntryDisplay {entry} /></li>
            {/each}
          </ul>
        </section>
      {:else}
        <div class="global">No results found.</div>
      {/if}
    {:else}
      <div class="global">
        <Spinner />
      </div>
    {/if}
  {:else}
    <div class="error">
      {$error}
    </div>
  {/if}
</div>

<style lang="scss">
  h2 {
    text-align: center;
  }

  ul {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .exact {
    ul {
      display: flex;
      gap: 1rem;
      justify-content: center;
      flex-wrap: wrap;

      margin: 0 1rem;
    }

    li {
      width: 14rem;
      height: 8rem;
    }

    .create {
      text-align: center;
    }
  }

  .objects {
    li {
      margin: 0.5em auto;
      max-width: 66em;
    }
  }

  .raw {
    li {
      margin: 1em auto;
      max-width: 66em;
    }
  }

  .global {
    font-size: 48px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
</style>
