<template>
  <template v-if="show">
    <text
      v-if="formDefineItem.type === 'static-text' "
      class="form-static-text"
      :style="(params.style as any)"
      :class="(params.class as any)"
    >
      {{ params?.text ?? modelValue ?? null }}
    </text>
    <uni-forms-item 
      v-else
      ref="formItemRef"
      :label="label"
      :name="formDefineItem.fullName"
      :required="Boolean(formDefineItem.rules?.length)"
      v-bind="formDefineItem.itemParams"
    >
      <!-- <text>fullName: {{formDefineItem.fullName}}</text> -->
      <template v-if="formDefineItem.type === 'text'">
        <uni-easyinput 
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          :maxlength="260"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'number'">
        <uni-number-box
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'radio'">
        <uni-data-checkbox
          ref="itemRef"
          selectedColor="#ff8719"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'select'">
        <uni-data-select 
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'checkbox'">
        <uni-data-checkbox 
          ref="itemRef"
          selectedColor="#ff8719"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'bool-checkbox'"> 
        <uni-data-checkbox 
          ref="itemRef"
          selectedColor="#ff8719"
          :modelValue="modelValue"
          :multiple="false"
          :localdata="[{text: '是', value: true}, {text: '否', value: false}]"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'boolint-checkbox'"> 
        <uni-data-checkbox 
          ref="itemRef"
          selectedColor="#ff8719"
          :modelValue="modelValue"
          :multiple="false"
          :localdata="[{text: '是', value: 1}, {text: '否', value: 0}]"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'dynamic-checkbox'">
        <DynamicCheckbox
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'dynamic-select'">
        <DynamicSelect
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'city-select'">
        <CityPicker
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'picker'">
        <uni-data-picker
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'lonlat-picker'">
        <LonlatPicker
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="(v:any) =>{onValueChanged(v);formItemRef.onFieldChange(v)}"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'textarea'">
        <uni-easyinput 
          ref="itemRef"
          type="textarea" 
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'richtext'">
        <RichTextEditor
          ref="itemRef"
          :modelValue="modelValue"
          @update:modelValue="onValueChanged"
          v-bind="params"
        />
      </template>
      <template v-else-if="formDefineItem.type === 'datetime-picker'">
        <uni-datetime-picker
          ref="itemRef"
          :value="modelValue"
          v-bind="params"
          @change="(e: any) => onValueChanged(e)"
        />
      </template>
      <!-- More components can be added here... -->
      <template v-else>
        <text>Fallback: unknow form type {{ formDefineItem.type }}</text>
      </template>
    </uni-forms-item>
  </template>
</template>

<script setup lang="ts">
import { computed, inject, onBeforeUnmount, onMounted, ref, type PropType } from 'vue';
import type { FormDefineItem, IFormItemCallback } from '.';
import DynamicSelect from './components/DynamicSelect.vue';
import CityPicker from './components/CityPicker.vue';
import LonlatPicker from './components/LonlatPicker.vue';
import DynamicCheckbox from './components/DynamicCheckbox.vue';
import RichTextEditor from './components/RichTextEditor.vue';

const props = defineProps({	
  parentModel: {
    type: null, //TODO: parentModel
  },
  modelValue: {
    type: null
  },
  formDefineItem: {
    type: Object as PropType<FormDefineItem>,
    default: () => ({})
  },
});

const formItemRef = ref();
const topModel = inject<any>('formTopModel', {});
const formGlobalParams = inject<any>('formGlobalParams', {});

function evaluateCallback(val: unknown|IFormItemCallback<unknown>) {
  if (typeof val === 'object' && typeof (val as IFormItemCallback<unknown>).callback === 'function')
    return (val as IFormItemCallback<unknown>).callback(
      props.modelValue, 
      topModel.value, 
      props.parentModel, 
      formGlobalParams.value,
      props.formDefineItem,
    );
  return val as unknown;
}
function evaluateCallbackObj(val: Record<string, unknown|IFormItemCallback<unknown>>) {
  const newObj = {} as Record<string, unknown>;
  for (const key in val) {
    if (Object.prototype.hasOwnProperty.call(val, key))
      newObj[key] = evaluateCallback(val[key]);
  }
  return newObj;
}

const params = computed(() => evaluateCallbackObj(props.formDefineItem.params as any))
const label = computed(() => evaluateCallback(props.formDefineItem.label))
const show = computed(() => props.formDefineItem.show == undefined || evaluateCallback(props.formDefineItem.show))

const itemRef = ref();
const emit = defineEmits([ 'update:modelValue' ]);
 
function onValueChanged(v: any) {
  props.formDefineItem.onChange?.(props.modelValue, v, topModel.value, itemRef.value);
  emit('update:modelValue', v);
}

onMounted(() => {
  props.formDefineItem.onMounted?.(topModel.value, itemRef.value);
})
onBeforeUnmount(() => {
  props.formDefineItem.onBeforeUnMount?.(topModel.value, itemRef.value); 
})

</script>