<script setup>
import { markRaw, computed, defineModel } from 'vue';
import { QIcon, QCheckbox } from 'quasar';
import { dashIfEmpty } from 'src/filters';

/* basic input */
import VnSelect from 'components/common/VnSelect.vue';
import VnSelectCache from 'components/common/VnSelectCache.vue';
import VnInput from 'components/common/VnInput.vue';
import VnInputNumber from 'components/common/VnInputNumber.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputTime from 'components/common/VnInputTime.vue';
import VnComponent from 'components/common/VnComponent.vue';
import VnUserLink from 'components/ui/VnUserLink.vue';

const model = defineModel(undefined, { required: true });
const $props = defineProps({
    column: {
        type: Object,
        required: true,
    },
    row: {
        type: Object,
        default: () => {},
    },
    default: {
        type: [Object, String],
        default: null,
    },
    componentProp: {
        type: String,
        default: null,
    },
    isEditable: {
        type: Boolean,
        default: true,
    },
    components: {
        type: Object,
        default: null,
    },
    showLabel: {
        type: Boolean,
        default: null,
    },
});

const defaultSelect = {
    attrs: {
        row: $props.row,
        disable: !$props.isEditable,
        class: 'fit',
    },
    forceAttrs: {
        label: $props.showLabel && $props.column.label,
    },
};

const defaultComponents = {
    input: {
        component: markRaw(VnInput),
        attrs: {
            disable: !$props.isEditable,
            class: 'fit',
        },
        forceAttrs: {
            label: $props.showLabel && $props.column.label,
        },
    },
    number: {
        component: markRaw(VnInputNumber),
        attrs: {
            disable: !$props.isEditable,
            class: 'fit',
        },
        forceAttrs: {
            label: $props.showLabel && $props.column.label,
        },
    },
    date: {
        component: markRaw(VnInputDate),
        attrs: {
            readonly: !$props.isEditable,
            disable: !$props.isEditable,
            style: 'min-width: 125px',
            class: 'fit',
        },
        forceAttrs: {
            label: $props.showLabel && $props.column.label,
        },
    },
    time: {
        component: markRaw(VnInputTime),
        attrs: {
            disable: !$props.isEditable,
        },
        forceAttrs: {
            label: $props.showLabel && $props.column.label,
        },
    },
    checkbox: {
        component: markRaw(QCheckbox),
        attrs: ({ model }) => {
            const defaultAttrs = {
                disable: !$props.isEditable,
                'model-value': Boolean(model),
                class: 'no-padding fit',
            };

            if (typeof model == 'number') {
                defaultAttrs['true-value'] = 1;
                defaultAttrs['false-value'] = 0;
            }
            return defaultAttrs;
        },
        forceAttrs: {
            label: $props.showLabel && $props.column.label,
        },
    },
    select: {
        component: markRaw(VnSelectCache),
        ...defaultSelect,
    },
    rawSelect: {
        component: markRaw(VnSelect),
        ...defaultSelect,
    },
    icon: {
        component: markRaw(QIcon),
    },
    userLink: {
        component: markRaw(VnUserLink),
    },
};

const value = computed(() => {
    return $props.column.format
        ? $props.column.format($props.row, dashIfEmpty)
        : dashIfEmpty($props.row[$props.column.name]);
});

const col = computed(() => {
    let newColumn = { ...$props.column };
    const specific = newColumn[$props.componentProp];
    if (specific) {
        newColumn = {
            ...newColumn,
            ...specific,
            ...specific.attrs,
            ...specific.forceAttrs,
        };
    }
    if (
        (/^is[A-Z]/.test(newColumn.name) || /^has[A-Z]/.test(newColumn.name)) &&
        newColumn.component == null
    )
        newColumn.component = 'checkbox';
    if ($props.default && !newColumn.component) newColumn.component = $props.default;

    return newColumn;
});

const components = computed(() => $props.components ?? defaultComponents);
</script>
<template>
    <div class="row no-wrap">
        <VnComponent
            v-if="col.before"
            :prop="col.before"
            :components="components"
            :value="{ row, model }"
            v-model="model"
        />
        <VnComponent
            v-if="col.component"
            :prop="col"
            :components="components"
            :value="{ row, model }"
            v-model="model"
        />
        <span :title="value" v-else>{{ value }}</span>
        <VnComponent
            v-if="col.after"
            :prop="col.after"
            :components="components"
            :value="{ row, model }"
            v-model="model"
        />
    </div>
</template>
