// Styles
import './VColorPickerEdit.sass'

// Components
import { VBtn } from '@/components/VBtn'

// Composables
import { makeComponentProps } from '@/composables/component'
import { useLocale } from '@/composables/locale'

// Utilities
import { computed } from 'vue'
import { modes, nullColor } from './util'
import { defineComponent, propsFactory, useRender } from '@/util'

// Types
import type { PropType } from 'vue'
import type { HSV } from '@/util/colorUtils'

const VColorPickerInput = ({ label, ...rest }: any) => {
  return (
    <div
      class="v-color-picker-edit__input"
    >
      <input { ...rest } />
      <span>{ label }</span>
    </div>
  )
}

export const makeVColorPickerEditProps = propsFactory({
  color: Object as PropType<HSV | null>,
  disabled: Boolean,
  hideInputLabels: Boolean,
  readonly: Boolean,
  mode: {
    type: String as PropType<keyof typeof modes>,
    default: 'rgba',
    validator: (v: string) => Object.keys(modes).includes(v),
  },
  modes: {
    type: Array as PropType<readonly (keyof typeof modes)[]>,
    default: () => Object.keys(modes),
    validator: (v: any) => Array.isArray(v) && v.every(m => Object.keys(modes).includes(m)),
  },

  ...makeComponentProps(),
}, 'VColorPickerEdit')

export const VColorPickerEdit = defineComponent({
  name: 'VColorPickerEdit',

  props: makeVColorPickerEditProps(),

  emits: {
    'update:color': (color: HSV) => true,
    'update:mode': (mode: keyof typeof modes) => true,
  },

  setup (props, { emit }) {
    const { t } = useLocale()
    const enabledModes = computed(() => {
      return props.modes.map(key => ({ ...modes[key], name: key }))
    })

    const inputs = computed(() => {
      const mode = enabledModes.value.find(m => m.name === props.mode)

      if (!mode) return []

      const color = props.color ? mode.to(props.color) : null

      return mode.inputs?.map(({ getValue, getColor, localeKey, ...inputProps }) => {
        return {
          ...mode.inputProps,
          ...inputProps,
          ariaLabel: t(`$vuetify.colorPicker.ariaLabel.${localeKey}`),
          disabled: props.disabled,
          readonly: props.readonly,
          value: color && getValue(color),
          onChange: (e: InputEvent) => {
            const target = e.target as HTMLInputElement | null

            if (!target) return

            emit('update:color', mode.from(getColor(color ?? mode.to(nullColor), target.value)))
          },
        }
      })
    })

    useRender(() => (
      <div
        class={[
          'v-color-picker-edit',
          props.class,
        ]}
        style={ props.style }
      >
        { inputs.value?.map(inputProps => (
          <VColorPickerInput
            { ...inputProps }
            label={ props.hideInputLabels ? undefined : inputProps.label }
          />
        ))}
        { enabledModes.value.length > 1 && (
          <VBtn
            icon="$unfold"
            size="x-small"
            variant="plain"
            aria-label={ t('$vuetify.colorPicker.ariaLabel.changeFormat') }
            onClick={ () => {
              const mi = enabledModes.value.findIndex(m => m.name === props.mode)

              emit('update:mode', enabledModes.value[(mi + 1) % enabledModes.value.length].name)
            }}
          />
        )}
      </div>
    ))

    return {}
  },
})

export type VColorPickerEdit = InstanceType<typeof VColorPickerEdit>
