<template>
  <el-form
    :label-position="labelPosition ?? 'right'"
    :label-width="labelWidth ?? '120px'"
    :model="query"
    :rules="rules"
    ref="formRef"
    v-bind="$attrs"
    v-on="$listeners"
  >
    <template v-for="(item, _i) in items">
      <el-form-item
        v-if="!item.hidden"
        :key="item.prop + _i || _i"
        v-bind="item"
      >
        <template v-if="!item.type">
          <slot :name="item.prop"></slot>
        </template>
        <template v-if="item.type === 'input'">
          <el-input v-bind="item.options" v-on="item.handles" v-model="query[item.prop]">
            <template v-for="slot in item.slots" :slot="slot">
              <slot :name="`${item.prop}.${slot}`"></slot>
            </template>
          </el-input>
        </template>
        <template v-if="item.type === 'autocomplete'">
          <el-autocomplete
            v-model="query[item.prop]"
            v-bind="item.options"
            v-on="item.handles"
          >
            <template v-for="slot in item.slots" :slot="scope">
              <slot :name="`${item.prop}.${slot}`" :scope="scope"></slot>
            </template>
          </el-autocomplete>
        </template>
        <template v-if="item.type === 'number'">
          <el-input-number v-bind="item.options" v-on="item.handles" v-model="query[item.prop]"></el-input-number>
        </template>
        <template v-if="item.type === 'select'">
          <el-select v-bind="item.options" v-on="item.handles" v-model="query[item.prop]">
            <template v-for="slot in item.slots" :slot="slot">
              <slot :name="`${item.prop}.${slot}`"></slot>
            </template>
            <template v-if="item.options.groups">
              <el-option-group
                v-for="group in item.options.groups"
                :key="group.label"
                :label="group.label"
              >
                <el-option
                  v-for="_item in group.items"
                  :key="_item.label"
                  v-bind="_item"
                >
                </el-option>
              </el-option-group>
            </template>
            <template v-else>
              <el-option
                v-for="_item in item.options.items"
                :key="_item.label"
                :label="_item[item.options.labelText ?? 'label']"
                :value="_item[item.options.labelValue ?? 'value']"
                :disable="_item.disable"
              ></el-option>
            </template>
          </el-select>
        </template>
        <template v-if="item.type === 'radioGroup'">
          <el-radio-group v-model="query[item.prop]" v-bind="item.options" v-on="item.handles">
            <template v-if="item.button">
              <el-radio-button
                v-for="_item in item.options.items"
                :key="_item.label"
                v-bind="_item"
              >
              {{ _item.text }}
              </el-radio-button>
            </template>
            <template v-else>
              <el-radio
                v-for="_item in item.options.items"
                :key="_item.label"
                v-model="query[item.prop]"
                v-bind="_item"
              >
                <span :style="_item.labelStyle || item.labelStyle">{{ _item.text }}</span>
              </el-radio>
            </template>
          </el-radio-group>
        </template>
        <template v-if="item.type === 'datePicker'">
          <el-date-picker v-bind="item.options" v-on="item.handles" v-model="query[item.prop]"></el-date-picker>
        </template>
        <template v-if="item.type === 'cascader'">
          <el-cascader
            v-model="query[item.prop]"
            v-bind="item.options"
            v-on="item.handles"
          ></el-cascader>
        </template>
        <template v-if="item.slotAfter">
          <slot :name="`${item.prop}.after`"></slot>
        </template>
      </el-form-item>
    </template>
    <slot></slot>
  </el-form>
</template>

<script>
export default {
  name: 'm-form',
  props: {
    labelWidth: String,
    labelPosition: String,
    value: {
      type: Object,
      default: () => {}
    },
    items: {
      type: Array,
      default: () => []
    }
  },
  data () {
    return {
      query: {
        ...this.value
      },
      rules: {}
    }
  },
  watch: {
    value: {
      handler (val) {
        this.query = val
      },
      deep: true
    },
    query: {
      handler (val) {
        this.$emit('input', val)
      },
      deep: true
    }
  },
  created () {
    this.rules = this.items.reduce((res, item) => {
      res[item.prop] = item.rules
      return res
    }, {})
  },
  methods: {
    resetFields () {
      this.$refs.formRef.resetFields()
    },
    clearValidate () {
      return this.$refs.formRef.clearValidate(...arguments)
    },
    validateField () {
      return this.$refs.formRef.validateField(...arguments)
    },
    validate (callback) {
      this.$refs.formRef.validate((valid) => {
        callback(valid)
      })
    }
  }
}
</script>

<style lang="scss" scoped>

</style>
