<script lang="ts">
  import BasicDropdown from "../basic-dropdown.webc.svelte";
  import { type FieldInfo } from "../field.svelte";
  import FieldDetails from "../field-details.svelte";

  const MAX_COL_WIDTH_PX = 800;
  const MIN_COL_WIDTH_PX = 160;

  type Props = {
    field: FieldInfo;
    index: number;
    ondragenter?(ev: DragEvent): unknown;
    ondragleave?(ev: DragEvent): unknown;
    ondragover?(ev: DragEvent): unknown;
    ondragstart?(ev: DragEvent): unknown;
    ondrop?(ev: DragEvent): unknown;
    onresize?(width_px: number): unknown;
  };

  let {
    field = $bindable(),
    index,
    ondragenter,
    ondragleave,
    ondragover,
    ondragstart,
    ondrop,
    onresize,
  }: Props = $props();

  const original_label_value = field.field.table_label;

  let type_indicator_element = $state<HTMLButtonElement | undefined>();
  let remove_field_dialog_element = $state<HTMLDialogElement | undefined>();
  let field_config_dialog_element = $state<HTMLDialogElement | undefined>();
  let name_value = $state(field.field.name);
  let label_value = $state(field.field.table_label ?? "");
  let resize_drag_x_start = $state<number | undefined>();

  $effect(() => {
    field.field.table_label = label_value === "" ? undefined : label_value;
  });
</script>

<div
  aria-colindex={index}
  class="field-header"
  draggable={true}
  {ondragenter}
  {ondragleave}
  {ondragover}
  {ondragstart}
  {ondrop}
  role="columnheader"
  style:--column-width={`${field.field.table_width_px}px`}
  tabindex={0}
>
  <div class="field-header__label">
    {field.field.table_label ?? field.field.name}
  </div>
  <BasicDropdown
    alignment="right"
    button_aria_label="Field options"
    on_toggle={(ev) => {
      if (ev.newState === "closed") {
        type_indicator_element?.focus();
        field.field.table_label = original_label_value;
        label_value = original_label_value ?? "";
      }
    }}
  >
    <span slot="button-contents">
      {#if field.field.presentation.t === "Dropdown"}
        <i class="ti ti-select"></i>
      {:else if field.field.presentation.t === "Numeric"}
        <i class="ti ti-decimal"></i>
      {:else if field.field.presentation.t === "Text"}
        <i class="ti ti-file-text"></i>
      {:else if field.field.presentation.t === "Timestamp"}
        <i class="ti ti-calendar"></i>
      {:else if field.field.presentation.t === "Uuid"}
        <i class="ti ti-id"></i>
      {/if}
    </span>
    <menu slot="popover" class="basic-dropdown__menu">
      <li>
        <button
          onclick={() => {
            field_config_dialog_element?.showModal();
          }}
          type="button"
        >
          {field.field.presentation.t} settings
        </button>
      </li>
      <li>
        <button
          onclick={() => {
            remove_field_dialog_element?.showModal();
          }}
          type="button"
        >
          Remove field
        </button>
      </li>
    </menu>
  </BasicDropdown>
</div>
<div
  class="field-resize-handle"
  draggable={true}
  ondragstart={(ev) => {
    resize_drag_x_start = ev.layerX;
  }}
  ondragend={(ev) => {
    if (resize_drag_x_start !== undefined) {
      onresize?.(
        Math.min(
          MAX_COL_WIDTH_PX,
          Math.max(
            MIN_COL_WIDTH_PX,
            field.field.table_width_px + ev.layerX - resize_drag_x_start,
          ),
        ),
      );
      resize_drag_x_start = undefined;
    }
  }}
  role="separator"
  aria-valuenow={field.field.table_width_px}
  aria-valuemin={MIN_COL_WIDTH_PX}
  aria-valuemax={MAX_COL_WIDTH_PX}
>
  <div class="field-resize-handle__v-border"></div>
</div>

<dialog bind:this={remove_field_dialog_element} class="dialog">
  <form method="post" action="remove-field">
    <div class="padded">
      <label style:display="block">
        <input type="radio" name="delete_data" value="false" checked />
        Hide field without deleting data.
      </label>
      <label style:display="block">
        <input type="radio" name="delete_data" value="true" />
        Remove field and underlying data. This cannot be undone.
      </label>
    </div>
    <div class="form__buttons">
      <input type="hidden" name="field_id" value={field.field.id} />
      <button class="button button--primary" type="submit">Remove</button>
      <button
        class="button button--secondary"
        onclick={() => remove_field_dialog_element?.close()}
        type="button"
      >
        Cancel
      </button>
    </div>
  </form>
</dialog>

<dialog bind:this={field_config_dialog_element} class="dialog">
  <form method="post" action="update-field">
    <div class="padded">
      <FieldDetails
        bind:name_value
        bind:label_value
        name_input_disabled
        presentation={field.field.presentation}
      />
    </div>
    <input type="hidden" name="field_id" value={field.field.id} />
    <div class="form__buttons">
      <button class="button button--primary" type="submit">Save</button>
    </div>
  </form>
</dialog>
