<template>
    <div v-if="types[type]" class="ui-input" :style="style" :class="{ require: props.require, error: props.error }">
        <component :is="types[type].component" v-bind="childProps" :model-value="props.modelValue" @update:model-value="newValue => emit('update:modelValue', newValue)">
            <template v-for="(slot, name) in $slots" #[name]="raw">
                <slot :name="name" v-bind="raw" />
            </template>
        </component>
        <slot />

        <p v-if="error" class="error-msg">{{ error }}</p>
    </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import radio from './radio.vue'
import checkbox from './checkbox.vue'
import text from './text.vue'
import select from './select.vue'
import range from './range.vue'
import textarea from './textarea.vue'
import number from './number.vue'
import uiSwitch from './switch.vue'
import file from './file.vue'
import search from './search.vue'
import richtext from './richtext.vue'
import {
    checkboxPropsDesc,
    filePropsDesc,
    inputPropsDesc,
    numberPropsDesc,
    radioPropsDesc,
    rangePropsDesc,
    richtextPropsDesc,
    searchPropsDesc,
    selectPropsDesc,
    switchPropsDesc,
    textPropsDesc,
    textareaPropsDesc,
} from './state.js.bk'

const types = {
    checkbox: {
        component: checkbox,
        propsDesc: checkboxPropsDesc,
    },
    text: {
        component: text,
        propsDesc: textPropsDesc,
    },
    select: {
        component: select,
        propsDesc: selectPropsDesc,
    },
    radio: {
        component: radio,
        propsDesc: radioPropsDesc,
    },
    range: {
        component: range,
        propsDesc: rangePropsDesc,
    },
    number: {
        component: number,
        propsDesc: numberPropsDesc,
    },
    switch: {
        component: uiSwitch,
        propsDesc: switchPropsDesc,
    },
    textarea: {
        component: textarea,
        propsDesc: textareaPropsDesc,
    },
    file: {
        component: file,
        propsDesc: filePropsDesc,
    },
    search: {
        component: search,
        propsDesc: searchPropsDesc,
    },
    richtext: {
        component: richtext,
        propsDesc: richtextPropsDesc,
    },
}

const props = defineProps(inputPropsDesc)

const emit = defineEmits(['update:modelValue'])
const type = computed(() => (types[props.type] ? props.type : 'text'))
const childProps = computed(() => {
    const retain = Object.keys(types[type.value].propsDesc)
    const childProps = {}
    for (const key in props) {
        if (retain.includes(key)) {
            childProps[key] = props[key]
        }
    }
    if (!types[props.type]) {
        childProps.type = props.type
    }
    return childProps
})

const style = computed(() => {
    const style = {}
    const keys = Object.keys(childProps.value)

    if (!keys.includes('width')) {
        style.width = props.width
    }

    if (!keys.includes('height')) {
        style.height = props.height
    }

    return style
})
</script>
