<!--
 * @Description:
-->
<template>
  <Col v-bind="colPropsComputed">
    <FormItem v-bind="{ ...formItemProps }">
      <template #label v-if="!formItemProps.hiddenLabel && schema.component !== 'Divider'">
        <Tooltip>
          <span>{{ schema.label }}</span>
          <template #title v-if="schema.helpMessage"
            ><span>{{ schema.helpMessage }}</span></template
          >
          <Icon v-if="schema.helpMessage" class="ml-5" icon="ant-design:question-circle-outlined" />
        </Tooltip>
      </template>
      <slot
        v-if="schema.componentProps && schema.componentProps?.slotName"
        :name="schema.componentProps.slotName"
        v-bind="schema"
      ></slot>
      <Divider
        v-else-if="schema.component == 'Divider' && schema.label && !formItemProps.hiddenLabel"
        >{{ schema.label }}
      </Divider>

      <!-- 部分控件需要一个空div -->
      <div>
        <Divider
          v-if="schema.field == 'MapGeom'"
          class="v-form-item-wrapper"
          :defaultValue="schema.defaultValue"
          v-bind="{ ...cmpProps, ...asyncProps }"
          :schema="schema"
          style="width: 100%; height: 10%"
          @change="handleChange"
          @click="handleClick(schema)"
        >
          图斑组件
        </Divider>
        <a-button
          v-else-if="['Button'].includes(schema.component)"
          :type="schema.componentProps.type"
          :shape="schema.componentProps.shape"
          :size="schema.componentProps.size"
          :defaultValue="schema.defaultValue"
          :schema="schema"
          :style="schema.width ? { width: schema.width } : {}"
          @change="handleChange"
          @click="handleClick(schema)"
        >
          <template #icon v-if="schema.componentProps.icon">
            <Icon :icon="schema.componentProps.icon" />
          </template>
          {{ schema.label }}
        </a-button>
        <div v-else-if="['CreateUser', 'ModifyUser'].includes(schema.component)">
          <a-input v-model:value="loginUserName" readOnly>
            <template #prefix>
              <user-outlined />
            </template>
          </a-input>
        </div>
        <div v-else-if="['CreateTime', 'ModifyTime'].includes(schema.component)">
          <a-input v-model:value="nowTime" readOnly>
            <template #prefix>
              <user-outlined />
            </template>
          </a-input>
        </div>
        <div v-else-if="schema.component == 'Select'">
          <a-select
            :placeholder="schema.componentProps.placeholder"
            :allowClear="schema.componentProps.allowClear"
            :mode="schema.componentProps.mode"
            :showSearch="schema.componentProps.showSearch"
            :disabled="schema.componentProps.disabled"
            :options="selectUseOptions ? schema.componentProps.options : showSelectDictionaryList"
            :defaultValue="schema.defaultValue"
          >
          </a-select>
        </div>
        <a-transfer
          v-else-if="['Transfer'].includes(schema.component)"
          :dataSource="schema.componentProps.dataSource"
          :targetKeys="schema.componentProps.targetKeys"
          :selectedKeys="schema.componentProps.selectedKeys"
          :schema="schema"
          :render="(item) => `${item.title} ${item.description}`"
          :titles="schema.componentProps.titles"
          :disabled="schema.componentProps.disabled"
          :oneWay="schema.componentProps.oneWay"
          :pagination="schema.componentProps.pagination"
          :showSearch="schema.componentProps.showSearch"
          :showSelectAll="schema.componentProps.showSelectAll"
          @change="transferChange"
          @search="transferSearch"
          @click="handleClick(schema)"
        />
        <component
          v-else
          class="v-form-item-wrapper"
          :is="componentItem"
          :defaultValue="schema.defaultValue"
          v-bind="{ ...cmpProps, ...asyncProps }"
          :schema="schema"
          :style="schema.width ? { width: schema.width } : {}"
          @change="handleChange"
          @click="handleClick(schema)"
        />
      </div>
    </FormItem>
  </Col>
</template>
<script lang="ts">
  import { type Recordable } from '@vben/types';
  import { defineComponent, reactive, toRefs, computed, PropType, unref } from 'vue';
  import { componentMap } from '../../core/formItemConfig';
  import { IVFormComponent, IFormConfig } from '../../typings/v-form-component';
  import { asyncComputed } from '@vueuse/core';
  import { handleAsyncOptions } from '../../utils';
  import { omit } from 'lodash-es';
  import { Tooltip, FormItem, Divider, Col } from 'ant-design-vue';
  import Icon from '@/components/Icon/Icon.vue';
  import { useFormModelState } from '../../hooks/useFormDesignState';
  import { UserOutlined } from '@ant-design/icons-vue';
  import dayjs from 'dayjs';
  import { useOnlineFormDesignStore } from '@/store/modules/onlineFormDesign';

  export default defineComponent({
    name: 'VFormItem',
    components: {
      Tooltip,
      Icon,
      FormItem,
      Divider,
      Col,
    },

    props: {
      formData: {
        type: Object,
        default: () => ({}),
      },
      schema: {
        type: Object as PropType<IVFormComponent>,
        required: true,
      },
      formConfig: {
        type: Object as PropType<IFormConfig>,
        required: true,
      },
    },
    emits: ['update:form-data', 'change'],
    setup(props, { emit }) {
      const state = reactive({
        componentMap,
        loginUserName: localStorage.getItem('fireUserLoginName'),
        nowTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      });
      const onlineFormDesignStore = useOnlineFormDesignStore();
      const { formModel: formData1, setFormModel } = useFormModelState();
      const colPropsComputed = computed(() => {
        const { colProps = {} } = props.schema;
        return colProps;
      });
      const selectUseOptions = computed(() => {
        if (props.schema.dataType === undefined || props.schema.dataType === '1') {
          return true;
        } else {
          return false;
        }
      });
      const showSelectDictionaryList = computed(() =>
        onlineFormDesignStore.getSelectOption(props.schema.field),
      );
      const formItemProps = computed(() => {
        const { formConfig } = unref(props);
        let { field, required, rules, labelCol, wrapperCol } = unref(props.schema);
        const { colon } = props.formConfig;

        const { itemProps } = unref(props.schema);

        //<editor-fold desc="布局属性">
        labelCol = labelCol
          ? labelCol
          : formConfig.layout === 'horizontal'
            ? formConfig.labelLayout === 'flex'
              ? { style: `width:${formConfig.labelWidth}px` }
              : formConfig.labelCol
            : {};

        wrapperCol = wrapperCol
          ? wrapperCol
          : formConfig.layout === 'horizontal'
            ? formConfig.labelLayout === 'flex'
              ? { style: 'width:auto;flex:1' }
              : formConfig.wrapperCol
            : {};

        const style =
          formConfig.layout === 'horizontal' && formConfig.labelLayout === 'flex'
            ? { display: 'flex' }
            : {};

        /**
         * 将字符串正则格式化成正则表达式
         */

        const newConfig = Object.assign(
          {},
          {
            name: field,
            style: { ...style },
            colon,
            required,
            rules,
            labelCol,
            wrapperCol,
          },
          itemProps,
        );
        if (!itemProps?.labelCol?.span) {
          newConfig.labelCol = labelCol;
        }
        if (!itemProps?.wrapperCol?.span) {
          newConfig.wrapperCol = wrapperCol;
        }
        if (!itemProps?.rules) {
          newConfig.rules = rules;
        }
        return newConfig;
      }) as Recordable<any>;

      const componentItem = computed(() => componentMap.get(props.schema.component as string));

      // console.log('component change:', props.schema.component, componentItem.value);
      const handleClick = (schema: IVFormComponent) => {
        if (schema.component === 'Button' && schema.componentProps?.handle)
          emit(schema.componentProps?.handle);
      };
      /**
       * 处理异步属性，异步属性会导致一些属性渲染错误，如defaultValue异步加载会导致渲染不出来，故而此处只处理options，treeData，同步属性在cmpProps中处理
       */
      const asyncProps = asyncComputed(async () => {
        let { options, treeData } = props.schema.componentProps ?? {};
        if (options) options = await handleAsyncOptions(options);
        if (treeData) treeData = await handleAsyncOptions(treeData);
        return {
          options,
          treeData,
        };
      });

      /**
       * 处理同步属性
       */
      const cmpProps = computed(() => {
        const isCheck =
          props.schema && ['Switch', 'Checkbox', 'Radio'].includes(props.schema.component);
        let { field } = props.schema;

        let { disabled, ...attrs } =
          omit(props.schema.componentProps, ['options', 'treeData']) ?? {};

        disabled = props.formConfig.disabled || disabled;

        return {
          ...attrs,
          disabled,
          [isCheck ? 'checked' : 'value']: formData1.value[field!],
        };
      });

      const handleChange = function (e) {
        const isCheck = ['Switch', 'Checkbox', 'Radio'].includes(props.schema.component);
        const target = e ? e.target : null;
        const value = target ? (isCheck ? target.checked : target.value) : e;
        setFormModel(props.schema.field!, value);
        emit('change', value);
      };

      // 穿梭框-左右穿梭
      const transferChange = (nextTargetKeys: string[], direction: string, moveKeys: string[]) => {
        props.schema.componentProps.targetKeys = nextTargetKeys;
      };
      // 穿梭框-查找
      const transferSearch = (dir: string, value: string) => {};
      // // 穿梭框-选中
      // const transferSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
      //   props.schema.componentProps.selectedKeys = sourceSelectedKeys.concat(targetSelectedKeys);
      // };
      return {
        ...toRefs(state),
        componentItem,
        formItemProps,
        handleClick,
        asyncProps,
        cmpProps,
        handleChange,
        colPropsComputed,
        selectUseOptions,
        showSelectDictionaryList,
        transferChange,
        transferSearch,
        // transferSelectChange,
      };
    },
  });
</script>

<style lang="less" scoped>
  .ml-5 {
    margin-left: 5px;
  }

  // form字段中的标签有ant-col，不能使用width:100%
  :deep(.ant-col) {
    width: auto;
  }

  .ant-form-item:not(.ant-form-item-with-help) {
    margin-bottom: 20px;
  }

  // .w-full {
  //   width: 100% !important;
  // }
</style>
