<template>
  <q-form ref="myForm" class="my-form row fit">
    <div
      :class="['item', item.col || 'col-12']"
      v-for="(item, index) in state.config"
      :key="index"
    >
      <template v-if="item.solt">
        <div>
          <slot :name="item.solt"></slot>
        </div>
      </template>
      <template v-else>
        <q-input
          v-if="item.type !== 'select'"
          :type="item.type"
          v-model="formValue[item.fild]"
          v-bind="item.bind"
          :disable="
            item.bind.disable === undefined ? state.disable : item.bind.disable
          "
          :readonly="
            item.bind.readonly === undefined
              ? state.readonly
              : item.bind.readonly
          "
        />
        <q-select
          v-if="item.type === 'select'"
          v-bind="item.bind"
          v-model="formValue[item.fild]"
          :disable="
            item.bind.disable === undefined ? state.disable : item.bind.disable
          "
          :readonly="
            item.bind.readonly === undefined
              ? state.readonly
              : item.bind.readonly
          "
        />
      </template>
    </div>
  </q-form>
</template>
<script lang="ts" setup>
import { onMounted, reactive, ref, watch } from 'vue';
import { cloneDeep, isObjEqual } from 'src/common/utils';

interface Props {
  config: any;
  modelValue: any;
  disable?: boolean;
  readonly?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
  config: () => {
    return {};
  },
  modelValue: () => {
    return {};
  },
  disable: false,
  readonly: false,
});

defineExpose({
  validate,
  reset,
});

const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void;
}>();

const myForm = ref<any>(null);

const state = reactive({
  config: cloneDeep(props.config),
  disable: props.disable,
  readonly: props.readonly,
});
const formValue = ref<any>(cloneDeep(props.modelValue));

watch(
  () => props.config,
  (val) => {
    state.config = cloneDeep(val);
  },
  {
    deep: true,
  }
);

watch(
  () => props.modelValue,
  (val: any) => {
    if (!isObjEqual(val, formValue.value)) {
      formValue.value = val;
    }
  },
  {
    deep: true,
  }
);

watch(
  formValue.value,
  (val) => {
    emit('update:modelValue', val);
  },
  { deep: true }
);

onMounted(() => {
  //
});

async function validate() {
  return await myForm.value.validate().then((success: any) => {
    if (success) {
      return true;
    } else {
      return false;
    }
  });
}

function reset() {
  myForm.value.resetValidation();
}
</script>

<style lang="scss" scoped>
.item {
  padding: $padding-sm;
}
</style>
