<script lang="ts">
  import { createEventDispatcher } from "svelte";
  import UpLink from "./display/UpLink.svelte";
  import { Component, UNTYPED, UpType, Widget } from "../lib/types";
  import Table from "./widgets/Table.svelte";
  import TableComponent from "./widgets/Table.svelte"; // silence false svelte(reactive-component) warnings
  import type { AttributeChange } from "../types/base";
  import type { UpEntry } from "upend";
  import Icon from "./utils/Icon.svelte";
  import IconButton from "./utils/IconButton.svelte";
  const dispatch = createEventDispatcher();

  export let address: string;
  export let entries: UpEntry[];
  export let type: UpType | undefined = undefined;
  export let title: String | undefined = undefined;
  export let editable = false;
  export let reverse = false;

  let currentWidget: string | undefined;

  let availableWidgets: Widget[] = [];
  $: {
    availableWidgets = [
      {
        name: "table",
        icon: "table",
        components: [
          {
            component: TableComponent,
          },
        ],
      },
    ];

    if (type?.widgetInfo) {
      availableWidgets = [type.widgetInfo, ...availableWidgets];
    }
    currentWidget = availableWidgets[0].name;
  }

  let components: Component[] = [];
  $: {
    components = availableWidgets.find(
      (w) => w.name === currentWidget
    )!.components;
  }

  async function onChange(change: AttributeChange) {
    switch (change.type) {
      case "create":
        await fetch(`/api/obj`, {
          method: "PUT",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            entity: address,
            attribute: change.attribute,
            value: change.value,
          }),
        });
        break;
      case "delete":
        await fetch(`/api/obj/${change.addr}`, { method: "DELETE" });
        break;
      case "update":
        // TODO
        await fetch(`/api/obj/${change.addr}`, { method: "DELETE" });
        await fetch(`/api/obj`, {
          method: "PUT",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            entity: address,
            attribute: change.attribute,
            value: change.value,
          }),
        });
        break;
      default:
        console.error("Unimplemented AttributeChange", change);
        return;
    }
    dispatch("changed");
  }
</script>

<section class="attribute-view">
  <header>
    <h3>
      {#if type && type !== UNTYPED}
        <UpLink to={{ entity: type.address }}>
          {#if type.icon}
            <div class="icon">
              <Icon name={type.icon} />
            </div>
          {/if}
          {type.name || "???"}
        </UpLink>
      {:else}
        {title || "???"}
      {/if}
    </h3>

    {#if currentWidget && (availableWidgets.length > 1 || editable)}
      <div class="views">
        {#each availableWidgets as widget (widget.name)}
          <IconButton
            name={widget.icon || "question-diamond"}
            active={widget.name === currentWidget}
            --active-color="var(--foreground)"
            on:click={() => (currentWidget = widget.name)}
          />
        {/each}
      </div>
    {/if}
  </header>
  {#if !reverse}
    {#each components as component}
      <svelte:component
        this={component.component}
        {...component.props || {}}
        {entries}
        {editable}
        on:change={(ev) => onChange(ev.detail)}
      />
    {/each}
  {:else}
    <Table columns="entity, attribute" {entries} />
  {/if}
</section>

<style scoped lang="scss">
  section {
    position: relative;
    overflow: visible;

    margin-top: 1.66em;
    padding: 1ex 0.95ex;

    border: 0.1em solid var(--foreground);
    border-radius: 4px;

    header {
      margin-bottom: 0.2em;

      & > * {
        position: absolute;
        top: -0.66em;

        margin: 0;

        background: var(--background-lighter);
        font-weight: 600;

        line-height: 1;
        padding: 0 0.75ex;

        .icon {
          display: inline-block;
          font-size: 1.25em;
          margin-top: -0.3em;
        }

        .icon {
          position: relative;
          bottom: -2px;
        }
      }

      h3 {
        left: 1ex;
      }

      .views {
        right: 1ex;

        font-size: 18px;
      }
    }
  }
</style>
