<script lang="ts">
  import debounce from "lodash/debounce";
  import { Readable, readable } from "svelte/store";
  import type { UpListing } 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";
  import { useNavigate } from "svelte-navigator";
  import { baseSearch, createLabelled, getObjects } from "../util/search";
  import { updateTitle } from "../util/title";
  const navigate = useNavigate();

  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 } = baseSearch(debouncedQuery));
    exactHits = [];
  }

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

  let exactHits = [];
  function onResolved(address: string, ids: string[]) {
    if (ids.some((id) => id.toLowerCase() === query.toLowerCase())) {
      if (!exactHits.includes(address)) {
        exactHits.push(address);
        exactHits = exactHits;
      }
    }
  }

  async function create() {
    const createdAddress = await createLabelled(query);
    navigate(`/browse/${createdAddress}`);
  }

  $: updateTitle("Search", query);
</script>

<div>
  {#if !$error}
    <section class="exact">
      {#if exactHits.length}
        <ul>
          {#each exactHits as address}
            <li>
              <UpObjectCard {address} --width="100%" --height="100%" />
            </li>
          {/each}
        </ul>
      {:else}
        <div class="create">
          <div>Create new object?</div>
          <button class="create-object" on:click={create}>"{query}"</button>
        </div>
      {/if}
    </section>
    {#if $result}
      <section class="objects">
        {#await objects}
          <h2>Objects</h2>
          <Spinner />
        {:then objects}
          {#if objects.length}
            <h2>Objects</h2>
            <ul>
              {#each objects as [address, _]}
                <li>
                  <UpObjectDisplay
                    {address}
                    link
                    on:resolved={(ids) => onResolved(address, ids.detail)}
                  />
                </li>
              {/each}
            </ul>
          {/if}
        {/await}
      </section>

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

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

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

  .exact {
    margin-top: 1rem;

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

      margin: 0 1rem;
    }

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

    .create {
      text-align: center;
    }

    .create-object {
      display: inline-block;
      color: var(--foreground);
      background: var(--background-lighter);
      border: 1px solid var(--foreground);
      border-radius: 4px;
      padding: 0.2em;
      font-size: 1.25em;
      cursor: pointer;
      margin-top: 1rem;
    }
  }

  .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>
