<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 {
    DEFAULT_EDITOR_STATE,
    editor_state_from_datum,
    type EditorState,
    datum_from_editor_state,
  } from "./editor-state.svelte";
  import { type FieldInfo } from "./field.svelte";
  import { type Presentation } from "./presentation.svelte";

  const ASSIGNABLE_PRESENTATIONS: Presentation[] = [
    { t: "Text", c: { input_mode: { t: "MultiLine", c: {} } } },
    { t: "Timestamp", c: {} },
    { t: "Uuid", c: {} },
  ];
  const ASSIGNABLE_FIELDS: FieldInfo[] = ASSIGNABLE_PRESENTATIONS.map(
    (presentation) => ({
      field: {
        id: "",
        table_label: "",
        name: "",
        presentation,
        table_width_px: -1,
      },
      not_null: true,
      has_default: false,
    }),
  );

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

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

  let editor_state = $state<EditorState>(
    value?.t === "Literal"
      ? editor_state_from_datum(value.c)
      : DEFAULT_EDITOR_STATE,
  );
  let editor_field_info = $state<FieldInfo>(ASSIGNABLE_FIELDS[0]);

  $effect(() => {
    if (value?.t === "Literal" && editor_field_info) {
      const datum_value = datum_from_editor_state(
        editor_state,
        editor_field_info.field.presentation,
      );
      if (datum_value) {
        value.c = datum_value;
      }
    }
  });

  function handle_identifier_selector_change(
    ev: Event & { currentTarget: HTMLSelectElement },
  ) {
    if (value?.t === "Identifier") {
      value.c.parts_raw = [ev.currentTarget.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:editor_state
            bind:field_info={editor_field_info}
            assignable_fields={ASSIGNABLE_FIELDS}
          />
        {/if}
      </div>
    </div>
  {/if}
</div>
