<script>
import { rules as ruleList } from '../utils/registRules';
import { registedComponentMapping } from '../utils/registComponents.js';
export default {
  functional: true,
  render(h, content) {
    const parent = content.parent;
    const { form, value, type, controlKey, option = {} } = content.props;
    const { layout = {}, formItem = {}, component = {} } = option;
    // 特殊处理的属性
    let { rules = [], label, data, disabled } = option;
    rules = rules ? (Array.isArray(rules) ? rules : [rules]) : [];
    label = label || (formItem.attrs ? formItem.attrs.label : '');
    data = data || (component.attrs ? component.attrs.data : undefined);
    disabled = disabled || (component.attrs ? component.attrs.disabled : false);

    const registedComponent = registedComponentMapping[type];

    // 组件的标签名
    const tagName = registedComponent
      ? registedComponent.tagName
      : type;
    // 组件注册时的默认属性
    const defaultAttrs = registedComponent
      ? registedComponent.defaultAttrs
      : {};
    // 组件注册时的默认样式
    const defaultStyles = registedComponent
      ? registedComponent.defaultStyles
      : {};
    let usedRules = [];
    // 对rules预处理
    for (const item of rules) {
      if (typeof item === 'string' && ruleList[item]) {
        usedRules.push(ruleList[item]);
      } else {
        // 区分函数校验和一般校验
        if (item.validator) {
          usedRules.push({
            ...item,
            validator: (rule, value, callback) => {
              item.validator(rule, value, callback, form);
            }
          });
        } else {
          usedRules.push(item);
        }
      }
    }
    // 不加这一行，校验不会触发，暂时不清楚原因
    // 加入一个空的校验规则，保证不会影响校验结果
    // BUG
    usedRules.push({
      validator: (rules, value, callback) => {
        callback();
      }
    });
    // 需要根据组件类型渲染
    // 不能直接h('el-col', layout)，会报错，数据监听的问题
    return h(
      'el-col',
      {
        props: layout.props,
        attrs: layout.attrs,
        style: layout.style,
        class: layout.class
      },
      [
        h(
          'el-form-item',
          {
            props: formItem.props,
            attrs: {
              ...formItem.attrs,
              prop: controlKey,
              rules: usedRules,
              label
            },
            style: formItem.style,
            class: formItem.class
          },
          [
            h(tagName, {
              props: component.props,
              attrs: {
                ...defaultAttrs,
                value: value,
                ...component.attrs,
                data,
                disabled
              },
              style: {
                ...defaultStyles,
                ...component.style
              },
              class: component.class,
              on: {
                input: parent.valueChange
              }
            })
          ]
        )
      ]
    );
  }
};
</script>
