<template>
    <div class="form">
      <div
        v-if="title"
        class="form-title"
        :style="titleStyle">
        {{title}}</div>
      <div v-if="isSlot">
        <slot></slot>
      </div>
      <div v-else>
        <div
          v-for="(item, index) in list"
          :key="index">
          <formItem
            :size="size"
            :data="item"
            :label="label"
            @lowMin="lowMin(arguments, item)"
            @highMax="highMax(arguments, item)"
            @getNumValue="getNumValue(arguments, item)"
            @riskDescChange="riskDescChange"
            @getRaValue="getRaValue(arguments, item)"
            @selectRight="select(item, index)"
            @blur="blur(item, index)"
            @focus="focus(item, index)"
            @update="update(item, index)">
          </formItem>
        </div>
        <slot></slot>
      </div>
    </div>
</template>
<script>
/*

第一次校验全部是否为空，为空的input着重显示为红色，显示第一个为空对象信息

第二次校验已经有的第一次其它规则

*/
import create from '../utils/create';
import verifyRules from './rules';
export default create({
  name: 'form',
  props: {
    title: {
      type: String
    },
    titleStyle: {
      type: Object
    },
    list: {
      type: Array
    },
    size: {
      type: String,
      default: 'default'
    },
    isSlot: {
      type: Boolean
    },
    parentIndex: {
      type: Number
    },
    label: {
      type: String
    }
  },
  data () {
    return {
      rules: {},
      errArray: [],
      optionsMap: []
    }
  },
  components: {
    formItem: () => import(
      './form-item'
      /* webpackChunkName: "form formItem" */
    )
  },
  methods: {
    riskDescChange(options) {
      // 如果visible是真的话就说明弹框该隐藏了
      if (options.visible) {
        options.visible = false
        return
      }
      // 如果点击是 其他的?号icon 先隐藏所有的弹框
      this.optionsMap.forEach((item) => {
        item.visible = false
      })
      // 给当前visible绑定上visible相应
      this.$set(options, 'visible', true)
      // 记录显示的元素
      this.optionsMap = [options]
    },
    // 是否是iPhone手机
    isIos () {
      let ua = window.navigator.userAgent.toLowerCase()
      return ua.includes('iphone os')
    },
    // 校验
    validate (callback) {
      if (this.isSlot) throw Error('当前处于slot状态，请自行校验')
      this.errArray = []
      const array = this.list
      array.forEach((item, index) => {
        this.rules[index] = item.rules
        // 有校验规则并且不是隐藏的数据，再去校验是否正确
        if (
          item.rules &&
          item.rules.length &&
          !item.hide
        ) {
          this.verifyRequired(item, index + 1)
        }
      })
      callback && callback(this.vs())
    },

    // verify status
    vs () {
      if (this.errArray.length) {
        // this.$notify({
        //   content: this.errArray[0].errmsg
        // })
        return this.listKeyObject(false, this.errArray[0].errmsg)
      } else {
        return this.listKeyObject(true)
      }
    },

    verifyRequired (item, index) {
      const { value, rules } = item
      rules.every(rule => {
        // 校验姓名是否合法
        if (
          value &&
          rule.cname &&
          !verifyRules.verifyName.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }
        // 校验是否为正数
        if (
          value &&
          rule.positiveNumber &&
          !verifyRules.verifyPositiveNumber.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }
        // 校验身份证是否合法
        if (
          value &&
          rule.idCard &&
          !verifyRules.verifyIdcard.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }

        // 校验电话号码是否合法
        if (
          value &&
          rule.phone
        ) {
          const newValue = value.replace(/[^\d]/g, '')
          if (!verifyRules.verifyPhone.test(newValue)) {
            this.verifyCorrectness(item, rule, index)
            return false
          }
        }

        // 校验邮箱是否合法
        if (
          value &&
          rule.email &&
          !verifyRules.verifyEmail.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }

        // 校验地址是否合法
        if (
          value &&
          rule.address &&
          !verifyRules.verifyAddress.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }

        // 校验银行卡号是否合法
        if (
          value &&
          rule.cardNo &&
          !verifyRules.verifyCreditCardNo.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }

        // 自定义校验规则校验
        if (
          value &&
          rule.custom &&
          !rule.custom.test(value)
        ) {
          this.verifyCorrectness(item, rule, index)
          return false
        }


        // 校验是否为空
        if (
          (
            value === '' ||
            value === null ||
            typeof value === 'undefined'
          ) &&
          rule.required
        ) {
          this.pushError(item, rule, index)
          return false
        }
        return true
      })
    },

    verifyCorrectness (item, rule, index) {
      const rul = Object.assign({}, rule)
      rul.errmsg = (this.label || '') + rule.errmsg
      this.pushError(item, rul, index)
    },

    getNameValue (name) {
      if (!this.list.length) return ''
      const item = this.list.find(item => item.name === name)
      if (!item) return ''
      return item.value || (item.raValue && item.raValue[0])
    },

    getValues () {
      let object = {}
      this.list.forEach(item => {
        // 如果是手机号，获取的时候清除一下字符
        if (item.rules && item.rules[1] && item.rules[1].phone) {
          item.value = item.value && item.value.replace(/[^\d]/g, '')
        }
        if (item.value || (item.raValue && item.raValue[0])) {
          object[item.name] = item.value || (item.raValue && item.raValue[0])
        }
      })
      return object
    },

    pushError (item, rule, index) {
      this.errArray.push(rule)
      this.$set(item, 'error', true)
    },

    // 根据list的name值转为对象形式回调回去
    listKeyObject (status, errmsg) {
      return {
        status: status,
        data: this.getValues(),
        errmsg
      }
    },

    callback (item, index) {
      return {
        item,
        index,
        parentIndex: this.parentIndex
      }
    },

    getRaValue (arg, item) {
      this.$emit(
        'getRaValue',
        {
          item: item,
          val: arg
        }
      )
    },
    getNumValue (arg, item) {
      this.$emit(
        'getNumValue',
        {
          item: item,
          value: arg && arg[0] && arg[0].value,
          type: arg && arg[0] && arg[0].type
        }
      )
    },
    lowMin (arg, item) {
      this.$emit(
        'lowMin',
        {
          item: item,
          val: arg
        }
      )
    },
    highMax (arg, item) {
      this.$emit(
        'highMax',
        {
          item: item,
          val: arg
        }
      )
    },
    select (item, index) {
      this.$emit(
        'select',
        this.callback(item, index))
    },
    update (item, index) {
      this.$emit('input',
        this.callback(item, index))
      this.$emit('change',
        this.callback(item, index))
    },
    // 最后一次blur 恢复位置
    // 如何知道最后一次呢，就看blur 触发的时候，focus 为 true or false
    blur (item, index) {
      if (this.isIos()) {
        this.blurStatus = true
        this.focusSatus = false
        // 因为离开一个输入框去另一个输入框，是先触发
        setTimeout(() => {
          if (this.focusSatus) return
          window.scroll(0, this.currentTop)
          this.blurStatus = false
        })
      }
      this.$emit('blur',
        this.callback(item, index))
    },
    // 第一次focus 记录 页面高度
    // blurStatu为true 说明不是第一次
    focus (item, index) {
      if (this.isIos()) {
        this.focusSatus = true
        if (this.blurStatus) return
        this.currentTop = document.documentElement.scrollTop || document.body.scrollTop
      }
      this.$emit('focus',
        this.callback(item, index))
    }
  }
})
</script>
