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

  import type { UpEntry, UpListing } from "upend";
import { query } from "../../lib/entity";
  import Thumbnail from "./gallery/Thumbnail.svelte";

  export let entries: UpEntry[];
  export let editable = 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 = entries
      .concat()
      .sort((aEntry, bEntry) => {
        if (
          !sortKeys[aEntry.value.c]?.length ||
          !sortKeys[bEntry.value.c]?.length
        ) {
          if (
            Boolean(sortKeys[aEntry.value.c]?.length) &&
            !sortKeys[bEntry.value.c]?.length
          ) {
            return -1;
          } else if (
            !sortKeys[aEntry.value.c]?.length &&
            Boolean(sortKeys[bEntry.value.c]?.length)
          ) {
            return 1;
          } else {
            return String(aEntry.value.c).localeCompare(String(bEntry.value.c));
          }
        } else {
          return sortKeys[aEntry.value.c][0].localeCompare(
            sortKeys[bEntry.value.c][0],
            undefined,
            { numeric: true, sensitivity: "base" }
          );
        }
      })
      .sort((aEntry, bEntry) => {
        return String(aEntry.value.c).length - String(bEntry.value.c).length;
      })
      .sort((aEntry, bEntry) => {
        return aEntry.attribute.localeCompare(bEntry.attribute);
      })
      .sort((aEntry, bEntry) => {
        if (
          !sortKeys[aEntry.entity]?.length ||
          !sortKeys[bEntry.entity]?.length
        ) {
          if (
            Boolean(sortKeys[aEntry.entity]?.length) &&
            !sortKeys[bEntry.entity]?.length
          ) {
            return -1;
          } else if (
            !sortKeys[aEntry.entity]?.length &&
            Boolean(sortKeys[bEntry.entity]?.length)
          ) {
            return 1;
          } else {
            return aEntry.entity.localeCompare(bEntry.entity);
          }
        } else {
          return sortKeys[aEntry.entity][0].localeCompare(
            sortKeys[bEntry.entity][0]
          );
        }
      });
  }

  $: {
    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">
      <Thumbnail
        address={String(entry.value.c)}
        on:resolved={(event) => {
          addSortKeys(String(entry.value.c), event.detail);
        }}
      />
    </div>
  {/each}
</div>

<style lang="scss">
  .gallery {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    align-items: center;
  }

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