<template>
  <el-form
    ref="form"
    v-bind="$attrs"
    :rules="rules"
    :model="form"
    :disabled="disabled"
    :label-width="labelWidth"
    :label-position="labelPosition"
  >
    <el-row v-for="i of (Math.ceil(totalSpan/24))" :key="'el-row-'+ i" :gutter="gutter">
      <template v-for="(item, index) of formItems">
        <el-col v-if="item.__prevSpan >= i*24 && item.__prevSpan < (i+1)*24" :key="'f-'+item.prop+index" v-permission="item.permission || []" :span="item.__span">
          <el-form-item :label="item.label" :prop="item.prop">
            <slot :name="item.prop" :field="item" :form="form">
              <my-field v-model="form[item.prop]" :type="item.type" :field="item" :props="item.props" @input="formChange" />
            </slot>
          </el-form-item>
        </el-col>
      </template>
    </el-row>
  </el-form>
</template>

<script>
import _ from 'lodash'
import MyField from './MyFormField'
import { fieldsManager } from '../utils'
export default {
  components: { MyField },
  props: {
    fields: {
      type: [Array, Object],
      default: () => []
    },
    defaultValue: {
      type: Object,
      default: () => ({})
    },
    disabled: {
      type: Boolean,
      default: false
    },
    labelWidth: {
      type: String || Number,
      default: '120px'
    },
    labelPosition: {
      type: String,
      default: 'right'
    },
    col: {
      type: Number,
      default: 1
    },
    gutter: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      formItems: [],
      totalSpan: 24,
      form: {},
      rules: {}
    }
  },
  watch: {
    fields() {
      this.initForm()
    },
    defaultValue() {
      this.initForm()
    }
  },
  created() {
    this.initForm()
  },
  methods: {
    initForm() {
      const fields = fieldsManager(this.fields)
      if (!fields || !fields.length) return
      const rules = {}
      fields.forEach((item) => {
        if (item.required) {
          rules[item.prop] = [{ required: true, message: '不能为空', trigger: 'change' }]
        }
        if (item.rule) {
          rules[item.prop] = item.rule
        }
      })
      const { col } = this
      const rowSpan = 24
      const defauleItemSpan = rowSpan / col
      let totalSpan = 24
      const rowTypeArr = ['multiple', 'image']
      this.formItems = fields.filter(item => !item.hidden).map(item => {
        let itemSpan = item.span || defauleItemSpan
        if (rowTypeArr.findIndex(type => type === item.type) !== -1) {
          itemSpan = item.span || rowSpan
        }
        item.__span = itemSpan
        item.__prevSpan = totalSpan
        totalSpan += itemSpan
        return item
      })
      this.totalSpan = totalSpan
      this.rules = rules
      this.resetFormData()
    },
    resetFormData() {
      this.form = { ...this.defaultValue }
      this.resetFields()
      this.$nextTick(() => {
        this.clearValidate()
      })
    },
    resetFields() {
      if (this.$refs['form']) this.$refs['form'].resetFields()
    },
    clearValidate() {
      if (this.$refs['form']) this.$refs['form'].clearValidate()
    },
    validate(callBack) {
      this.$refs['form'].validate(callBack)
    },
    getFormData() {
      const { form } = this
      return Object.keys(form).reduce((prev, key) => {
        _.set(prev, key, form[key])
        return prev
      }, {})
    },
    formChange() {
      const data = this.getFormData()
      this.$emit('change', data)
    }
  }
}
</script>
