<script lang="ts">
  import { readable, Readable } from "svelte/store";

  import type { UpEntry, UpListing } from "upend";
  import { query } from "../../lib/entity";
  import { defaultEntitySort, entityValueSort } from "../../util/sort";
  import BlobPreview from "../display/BlobPreview.svelte";
  import UpLink from "../display/UpLink.svelte";
  import UpObject from "../display/UpObject.svelte";

  export let entries: UpEntry[];
  export const editable = false;
  export let showEntities = false;

  // Sorting
  let sortedAttributes = entries;

  let sortKeys: { [key: string]: string[] } = {};
  function addSortKeys(key: string, vals: string[], resort = true) {
    if (!sortKeys[key]) {
      sortKeys[key] = [];
    }
    let changed = false;
    vals.forEach((val) => {
      if (!sortKeys[key].includes(val)) {
        changed = true;
        sortKeys[key].push(val);
      }
    });

    if (resort && changed) sortAttributes();
  }

  // Labelling
  let labelListing: Readable<UpListing> = readable(undefined);
  $: {
    const addresses = [];
    entries
      .flatMap((e) =>
        e.value.t === "Address" ? [e.entity, e.value.c] : [e.entity]
      )
      .forEach((addr) => {
        if (!addresses.includes(addr)) {
          addresses.push(addr);
        }
      });

    const addressesString = addresses.map((addr) => `"${addr}"`).join(" ");

    labelListing = query(`(matches (in ${addressesString}) "LBL" ? )`).result;
  }

  function sortAttributes() {
    sortedAttributes = showEntities
      ? entityValueSort(entries, sortKeys)
      : defaultEntitySort(entries, sortKeys);
  }

  $: {
    if ($labelListing) {
      entries.forEach((entry) => {
        addSortKeys(
          entry.entity,
          $labelListing.getObject(entry.entity).identify()
        );

        if (entry.value.t === "Address") {
          addSortKeys(
            entry.value.c,
            $labelListing.getObject(String(entry.value.c)).identify(),
            false
          );
        }
      });
      sortAttributes();
    }
  }

  entries.forEach((entry) => {
    addSortKeys(entry.entity, entry.listing.getObject(entry.entity).identify());
    if (entry.value.t === "Address") {
      addSortKeys(
        entry.value.c,
        entry.listing.getObject(String(entry.value.c)).identify(),
        false
      );
    }
  });

  sortAttributes();
</script>

<div class="gallery">
  {#each sortedAttributes as entry (entry.address)}
    <div class="thumbnail">
      <UpLink
        to={{ entity: String(showEntities ? entry.entity : entry.value.c) }}
      >
        <BlobPreview
          address={String(showEntities ? entry.entity : entry.value.c)}
        />
        <div class="label">
          <UpObject
            address={String(showEntities ? entry.entity : entry.value.c)}
            on:resolved={(event) => {
              addSortKeys(String(entry.value.c), event.detail);
            }}
          />
        </div>
      </UpLink>
    </div>
  {/each}
</div>

<style lang="scss">
  .thumbnail {
    border: 1px solid var(--foreground);
    border-radius: 4px;
    padding: 0.25em;
  }

  .gallery {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    align-items: flex-end;
  }

  .thumbnail {
    flex-grow: 1;
    min-width: 0;
    flex-basis: 20%;
  }
</style>
