<script
  lang="ts"
  generics="O extends any, V, P extends string | boolean = string | boolean"
>
  import Field from "./Field.svelte"
  import Select from "./Core/Select.svelte"
  import { createEventDispatcher } from "svelte"
  import { PopoverAlignment } from "../constants"
  import type { LabelPosition } from "../types"

  export let value: V | undefined = undefined
  export let label: string | undefined = undefined
  export let disabled: boolean = false
  export let readonly: boolean = false
  export let labelPosition: LabelPosition = "above"
  export let error: string | undefined = undefined
  export let placeholder: P = "Choose an option" as P
  export let options: O[] = []
  export let getOptionLabel = (option: O, _index?: number) =>
    extractProperty(option, "label")
  export let getOptionValue = (option: O, _index?: number) =>
    extractProperty(option, "value")
  export let getOptionSubtitle = (option: O, _index?: number) =>
    (option as any)?.subtitle
  export let getOptionTooltip = (option: O, _index?: number) =>
    (option as any)?.tooltip
  export let showSelectedSubtitle = false
  export let getOptionIcon = (option: O, _index?: number) =>
    (option as any)?.icon
  export let getOptionColour = (option: O, _index?: number) =>
    (option as any)?.colour
  export let useOptionIconImage = false
  export let isOptionEnabled:
    | ((_option: O, _index?: number) => boolean)
    | undefined = undefined
  export let quiet: boolean = false
  export let size: "S" | "M" | "L" = "M"
  export let bordered: boolean = true
  export let autoWidth: boolean = false
  export let popoverAutoWidth: boolean = false
  export let sort: boolean = false
  export let tooltip: string | undefined = undefined
  export let tooltipMessage:
    | ((_option: O, _index?: number) => string)
    | undefined = undefined
  export let autocomplete: boolean = false
  export let customPopoverHeight: string | undefined = undefined
  export let align: PopoverAlignment | undefined = PopoverAlignment.Left
  export let footer: string | undefined = undefined
  export let helpText: string | undefined = undefined
  export let compare: any = undefined
  export let onOptionMouseenter = () => {}
  export let onOptionMouseleave = () => {}
  export let loading: boolean | undefined = false
  export let searchPlaceholder: string | undefined = undefined
  export let required: boolean | undefined = false
  export let wrapText: boolean = false
  export let description: string | undefined = undefined

  type ChangeValue = P extends false | "" ? V : V | undefined

  const dispatch = createEventDispatcher<{ change: ChangeValue }>()
  const onChange = (e: CustomEvent<ChangeValue>) => {
    value = e.detail
    dispatch("change", e.detail)
  }

  const extractProperty = (value: any, property: any) => {
    if (value && typeof value === "object") {
      return value[property]
    }
    return value
  }
</script>

<Field
  {helpText}
  {label}
  {labelPosition}
  {error}
  {tooltip}
  {required}
  {description}
>
  <Select
    {size}
    {bordered}
    {quiet}
    {loading}
    {disabled}
    {readonly}
    {value}
    {options}
    {placeholder}
    {autoWidth}
    {popoverAutoWidth}
    {sort}
    {align}
    {footer}
    {getOptionLabel}
    {getOptionValue}
    {getOptionIcon}
    {getOptionColour}
    {getOptionSubtitle}
    {getOptionTooltip}
    {showSelectedSubtitle}
    {useOptionIconImage}
    {isOptionEnabled}
    {autocomplete}
    {customPopoverHeight}
    {compare}
    {onOptionMouseenter}
    {onOptionMouseleave}
    {tooltipMessage}
    {searchPlaceholder}
    {wrapText}
    on:change={onChange}
    on:click
  />
</Field>
