<script lang="ts">
  import { utc } from "@date-fns/utc";
  import { format as format_date } from "date-fns";

  import { type Datum } from "../datum.svelte";
  import { type FieldInfo } from "../field.svelte";
  import { type Coords } from "./coords.svelte";

  type Props = {
    coords: Coords;
    cursor: boolean;
    field: FieldInfo;
    onbecomecursor?(focus: () => unknown): unknown;
    oncopy?(ev: ClipboardEvent): unknown;
    ondblclick?(ev: MouseEvent, coords: Coords): unknown;
    onfocus?(ev: FocusEvent, coords: Coords): unknown;
    onkeydown?(ev: KeyboardEvent, coords: Coords): unknown;
    onmousedown?(ev: MouseEvent, coords: Coords): unknown;
    onpaste?(ev: ClipboardEvent): unknown;
    selected: boolean;
    table_region: "main" | "inserter";
    value: Datum;
  };

  let {
    coords,
    cursor,
    field,
    oncopy,
    onbecomecursor,
    ondblclick,
    onfocus,
    onkeydown,
    onmousedown,
    onpaste,
    selected,
    table_region,
    value,
  }: Props = $props();

  let cell_element = $state<HTMLDivElement | undefined>();

  let invalid_value = $derived(
    field.not_null && !field.has_default && value.c === undefined,
  );
  let null_value_class = $derived(
    table_region === "inserter" && field.has_default
      ? "ti-sparkles"
      : "ti-cube-3d-sphere-off",
  );

  $effect(() => {
    if (cursor) {
      onbecomecursor?.(() => cell_element?.focus());
      cell_element?.focus();
    }
  });
</script>

<div
  aria-colindex={coords.field_idx}
  aria-rowindex={coords.row_idx}
  aria-selected={selected}
  bind:this={cell_element}
  class="table-viewer__cell"
  {oncopy}
  ondblclick={(ev) => ondblclick?.(ev, coords)}
  onfocus={(ev) => onfocus?.(ev, coords)}
  onkeydown={(ev) => onkeydown?.(ev, coords)}
  onmousedown={(ev) => onmousedown?.(ev, coords)}
  {onpaste}
  role="gridcell"
  style:width={`${field.field.table_width_px}px`}
  tabindex={selected ? 0 : -1}
>
  <div
    class="table-viewer__cell-container"
    class:table-viewer__cell-container--cursor={cursor}
    class:table-viewer__cell-container--selected={selected}
  >
    {#if field.field.presentation.t === "Dropdown"}
      {#if value.t === "Text"}
        <div
          class="table-viewer__cell-content table-viewer__cell-content--dropdown"
          class:table-viewer__cell-content--null={value.c === undefined}
        >
          {#if value.c === undefined}
            <i class={["ti", null_value_class]}></i>
          {:else}
            <!-- FIXME: validate or escape dropdown_option.color -->
            <div
              class={[
                "dropdown-option-badge",
                `dropdown-option-badge--${
                  field.field.presentation.c.options
                    .find((option) => option.value === value.c)
                    ?.color.toLocaleLowerCase("en-US") ?? "grey"
                }`,
              ]}
            >
              {value.c}
            </div>
          {/if}
        </div>
      {:else}
        UNKNOWN
      {/if}
    {:else if field.field.presentation.t === "Numeric"}
      <div
        class="table-viewer__cell-content table-viewer__cell-content--numeric"
        class:table-viewer__cell-content--null={value.c === undefined}
      >
        {#if value.c === undefined}
          <i class={["ti", null_value_class]}></i>
        {:else}
          {value.c}
        {/if}
      </div>
    {:else if field.field.presentation.t === "Text"}
      <div
        class="table-viewer__cell-content table-viewer__cell-content--text"
        class:table-viewer__cell-content--null={value.c === undefined}
      >
        {#if value.c === undefined}
          <i class={["ti", null_value_class]}></i>
        {:else}
          {value.c}
        {/if}
      </div>
    {:else if field.field.presentation.t === "Uuid"}
      <div
        class="table-viewer__cell-content table-viewer__cell-content--uuid"
        class:table-viewer__cell-content--null={value.c === undefined}
      >
        {#if value.c === undefined}
          <i class={["ti", null_value_class]}></i>
        {:else}
          {value.c}
        {/if}
      </div>
    {:else if field.field.presentation.t === "Timestamp"}
      <div
        class="table-viewer__cell-content table-viewer__cell-content--timestamp"
        class:table-viewer__cell-content--null={value.c === undefined}
      >
        {#if value.c === undefined}
          <i class={["ti", null_value_class]}></i>
        {:else}
          {format_date(value.c, field.field.presentation.c.format, { in: utc })}
        {/if}
      </div>
    {:else}
      <div
        class="table-viewer__cell-content table-viewer__cell-content--unknown"
      >
        <div>UNKNOWN</div>
      </div>
    {/if}
    {#if value.t === "Text" && /^[a-z+.-]+:\/\/\S+$/i.test(value.c ?? "")}
      <a class="table-viewer__cell-indicator" href={value.c}
        ><i class="ti ti-external-link"><div class="sr-only">Open link</div></i
        ></a
      >
    {/if}
    {#if invalid_value}
      <div class="table-viewer__cell-notice">
        <i class="ti ti-alert-circle"></i>
      </div>
    {/if}
  </div>
</div>
