<template>
  <form
    class="bx-form"
    :class="ignoreLastLine && 'bx-form--ignoredline'"
    >
    <slot />
  </form>
</template>
<script>
import Vue from 'vue'
import scrollIntoView from 'scroll-into-view-if-needed'
import PromiseSequential from 'promise-sequential'
import { create } from '../utils'
import Toast from '../toast'

export default create({
  name: 'form',
  provide() {
    return {
      bxsForm: this,
    }
  },
  props: {
    model: Object,
    rules: Object,
    // 可选，是否显示校验错误信息
    showMessage: {
      type: Boolean,
      default: true,
    },
    // 可选，是否自动定位至错误项
    autoPositionError: {
      type: Boolean,
      default: true,
    },
    // 可选，是否自动显示Toast提示
    autoShowToast: {
      type: Boolean,
      default: true,
    },
    // 可选，默认Toast提示文案
    toastMessage: {
      type: String,
      default: '请完善填写内容',
    },
    // 可选，是否忽略最后一项的分割线
    ignoreLastLine: {
      type: Boolean,
      default: true,
    },
    // 可选，是否所有内容垂直对齐
    isContentVerticalAlignment: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      fields: [],
    }
  },
  watch: {
    isContentVerticalAlignment: {
      handler() {
        this.$nextTick(this.reCalculateLabelWidth)
      },
      immediate: true,
    },
  },
  created() {
    this.$on('form.addField', field => {
      this.fields.push(field)
    })
  },
  methods: {
    getFieldByProp(prop) {
      const fields = this.fields.filter(field => field.prop === prop)
      if (fields && fields.length > 0) {
        return fields[0]
      }
      return {}
    },
    validate(prop) {
      if (prop) {
        const field = this.getFieldByProp(prop)
        return field.validate()
      }
      return new Promise((resolve, reject) => {
        PromiseSequential(this.fields.map(field => () => field.validate()))
          .then(() => {
            resolve()
          })
          .catch(({ errors }) => {
            if (this.autoPositionError) {
              this.readyPositionErrorField(errors[0].field)
            }
            if (this.autoShowToast) {
              Toast(this.toastMessage)
            }
            reject(errors)
          })
      })
    },
    // 支持多个Form表单定位
    readyPositionErrorField(prop) {
      if (!Vue.bxsFormErrorFields) {
        Vue.bxsFormErrorFields = []
      }
      Vue.bxsFormErrorFields.push(prop)
      // 增加macroTask(setTimeout)，保证在microTask(PromiseSequential)后执行
      window.setTimeout(() => {
        this.autoPositionErrorField(Vue.bxsFormErrorFields[0])
        Vue.bxsFormErrorFields = []
      })
    },
    // 自动定位到错误项
    autoPositionErrorField(prop) {
      const { $el } = this.getFieldByProp(prop)
      if ($el) {
        scrollIntoView($el, {
          behavior: 'smooth',
          scrollMode: 'if-needed',
        })
      }
    },
    // 重新计算每一项label的宽度
    reCalculateLabelWidth() {
      if (this.isContentVerticalAlignment) {
        const fields = this.fields.filter(
          field => field.label && field.isLabelMoreThanThreshold,
        )
        if (fields.length > 0) {
          /* eslint no-param-reassign: ["error", { "props": false }] */
          this.fields.forEach(field => {
            field.isVerticalAlignmentForced = true
          })
        }
      } else {
        /* eslint no-param-reassign: ["error", { "props": false }] */
        this.fields.forEach(field => {
          field.isVerticalAlignmentForced = false
        })
      }
    },
    resetFields(prop) {
      if (prop) {
        const field = this.getFieldByProp(prop)
        field.resetField()
      } else {
        this.fields.forEach(field => {
          field.resetField()
        })
      }
    },
  },
})
</script>
<style>
@import './index.css';
</style>
