<svelte:options
  customElement={{
    props: {
      identifier_hints: { attribute: "identifier-hints", type: "Array" },
      value: { reflect: true, type: "Object" },
    },
    shadow: "none",
    tag: "expression-editor",
  }}
/>

<script lang="ts">
  import DatumEditor from "./datum-editor.svelte";
  import ExpressionSelector from "./expression-selector.svelte";
  import { type PgExpressionAny } from "./expression.svelte";
  import ExpressionEditor from "./expression-editor.webc.svelte";
  import { RFC_3339_S, type Presentation } from "./presentation.svelte";
  import type { Datum } from "./datum.svelte";

  const POTENTIAL_PRESENTATIONS: Presentation[] = [
    { t: "Numeric", c: {} },
    { t: "Text", c: { input_mode: { t: "MultiLine", c: {} } } },
    { t: "Timestamp", c: { format: RFC_3339_S } },
    { t: "Uuid", c: {} },
  ];

  type Props = {
    identifier_hints?: string[];
    value?: PgExpressionAny;
  };

  let { identifier_hints = [], value = $bindable() }: Props = $props();

  // Dynamic state to bind to datum editor.
  let editor_value = $state<Datum | undefined>();
  let editor_presentation = $state<Presentation>(POTENTIAL_PRESENTATIONS[0]);

  $effect(() => {
    editor_value = value?.t === "Literal" ? value.c : undefined;
  });

  function handle_identifier_selector_change(
    ev: Event & { currentTarget: HTMLSelectElement },
  ) {
    if (value?.t === "Identifier") {
      value.c.parts_raw = [ev.currentTarget.value];
    }
  }

  function handle_editor_change(datum_value: Datum) {
    if (value?.t === "Literal") {
      value.c = datum_value;
    }
  }
</script>

<div class="expression-editor__container">
  <div class="expression-editor__sidebar">
    <ExpressionSelector bind:value />
  </div>
  {#if value !== undefined}
    <div class="expression-editor__main">
      <div class="expression-editor__params">
        {#if value.t === "Comparison"}
          {#if value.c.t === "Infix"}
            <ExpressionEditor bind:value={value.c.c.lhs} {identifier_hints} />
            <ExpressionEditor bind:value={value.c.c.rhs} {identifier_hints} />
          {:else if value.c.t === "IsNull" || value.c.t === "IsNotNull"}
            <ExpressionEditor bind:value={value.c.c.lhs} {identifier_hints} />
          {/if}
        {:else if value.t === "Identifier"}
          <select
            onchange={handle_identifier_selector_change}
            value={value.c.parts_raw[0]}
          >
            {#each identifier_hints as hint}
              <option value={hint}>{hint}</option>
            {/each}
          </select>
        {:else if value.t === "Literal"}
          <DatumEditor
            bind:current_presentation={editor_presentation}
            bind:value={editor_value}
            potential_presentations={POTENTIAL_PRESENTATIONS}
            on_change={handle_editor_change}
          />
        {/if}
      </div>
    </div>
  {/if}
</div>
