<template>
  <div class="van-fr ibps-fixed-toolbar">
    <!-- fr-header  表头-->
    <slot
      v-if="formDef.name"
      name="fr-header"
    >
      <div class="van-block__title van-ellipsis">
        {{ formDef.name }}
      </div>
      <div v-if="formDef.desc" class="van-block__desc">
        {{ formDef.desc }}
      </div>
    </slot>
    <!-- fr-header  表单内容-->
    <div :style="bodyStyle" class="van-fr-body">
      <ibps-dynamic-form
        ref="dynamicForm"
        v-model="formData"
        :form-def="formDefData"
        :permissions="permissions"
        :readonly="readonly"
        :params="params"
        :input-align="inputAlign"
        :initialization="initialization"
        :cur-active-step.sync="curActiveStep"
        @load-script="loadScript"
      />
    </div>
    <!-- fr-toolbar  表单操作按钮-->
    <slot name="fr-toolbar">
      <ibps-toolbar
        v-if="hasActions"
        ref="frToolbar"
        :actions="actions"
        :more-actions="moreActions"
        icon-prefix="ibps-icon"
      />
    </slot>
    <slot ref="frExt" name="fr-ext" />
  </div>
</template>

<script>
import ActionUtils from '@/utils/action'
import JForm from '../utils/JForm'// 自定义脚本
import '../dynamic-form' // 动态表单
import IbpsToolbar from '@/components/ibps-toolbar'// 工具栏

const JFormId = 'JForm'

export default {
  components: {
    IbpsToolbar
  },
  props: {
    formDef: {
      type: Object,
      required: true
    },
    data: {
      type: Object
    },
    /**
     * @description 工具栏
     */
    buttons: {
      type: Array
    },
    /**
     * 是否只读 (流程实例时候控制)
     */
    readonly: {
      type: Boolean,
      default: false
    },
    /**
     *  @description 扩展参数 比如流程id等
     *流程相关信息:
     * taskId:任务id
     * instId：流程实例
     * defId：定义Id
     * formOpinionData： 流程意见配置及已经审批的意见数据
     */
    params: {
      type: Object
    },
    mode: { // 表单模式
      type: String
    },
    inputAlign: {
      type: String
    }
  },
  data() {
    return {
      loading: false,
      formData: {},
      permissions: null,
      initialization: false,
      formParams: {},
      curActiveStep: 0,
      curTime: new Date().getTime(),
      stepLoading: false,

      btnNum: this.getBtnNumByWidth()
    }
  },
  computed: {
    formDefData() {
      return JSON.parse(JSON.stringify(this.formDef))
    },

    actions() {
      if (this.toolbars.length > this.btnNum) {
        return this.toolbars.slice(0, this.btnNum)
      } else {
        return this.toolbars
      }
    },
    moreActions() {
      if (this.toolbars.length > this.btnNum) {
        return this.toolbars.slice(this.btnNum, this.toolbars.length)
      } else {
        return null
      }
    },
    toolbars() {
      return this.getActions()
    },
    hasActions() {
      // this.hasStepButton ||
      return this.actions && this.actions.length > 0
    },
    dynamicForm() {
      return this.$refs ? this.$refs.dynamicForm : null
    },
    hasStepButton() {
      return this.$utils.isNotEmpty(this.stepButtons) && this.mode !== 'dialog'
    },
    stepNum() {
      if (this.$utils.isEmpty(this.step)) {
        return 0
      }
      return this.step.field_options.columns.length
    },
    finishStep() {
      return this.stepNum - 1 === this.curActiveStep
    },
    stepButtons() {
      return this.getStepButtons()
    },
    step() {
      return this.getFormStep()
    },
    bodyStyle() {
      if (this.$isServer) {
        return
      }
      // header高度82px, fr actions高度50px，如果改动了样式自己传下bodyOffsetTop调整下
      const maxHeight = window.innerHeight - this.bodyOffsetTop
      return {
        maxHeight: maxHeight + 'px'
      }
    }
  },
  watch: {
    formDef: {
      handler: function(val, oldVal) {
        if (val && val !== oldVal) {
          this.initialization = false
          this.initUI()
        }
      },
      immediate: true
    },
    data: {
      handler: function(val, oldVal) {
        if (val && val !== oldVal) {
          const data = JSON.parse(JSON.stringify(val))
          // 表单数据
          this.formData = data.responses || {}
          // 表单权限
          this.permissions = data.permissions || null
        }
      },
      immediate: true,
      deep: true
    },
    curActiveStep() {
      this.$emit('cur-active-step', this.curActiveStep)
    }
  },
  created() {
    this.initUI()
  },
  destroyed() {
    const script = document.getElementById(JFormId)
    if (script) {
      script.parentNode.removeChild(script)
    }
  },
  methods: {
    getBtnNumByWidth() {
      const width = document.documentElement.clientWidth
      if (width >= 375) return 3
      else return 2
    },
    initUI() {
      if (!this.initialization) {
        this.initJForm()
        this.initialization = true
        this.$nextTick(() => {
          setTimeout(() => {
            this.loadScript()
          }, 10)
        })
      }
    },
    getActions() {
      if (this.$utils.isEmpty(this.buttons)) {
        return []
      }

      const actions = []
      this.buttons.forEach((btn, i) => {
        const key = btn.getAlias()
        let disabled = false
        let hidden = false
        // if (btn.getAlias() !== 'close' && this.hasStepButton && !this.finishStep) {
        //   disabled = true
        // }

        hidden = this.onLoadActions(key, btn, 'hidden', hidden)
        disabled = this.onLoadActions(key, btn, 'disabled', disabled)

        const button = {
          key: key,
          name: btn.getLabel(),
          icon: btn.getIcon(),
          type: btn.getStyle(),
          plain: btn.getPlain(),
          disabled: disabled,
          hidden: hidden,
          callback: () => {
            if (i >= this.btnNum) {
              this.closeMoreAction()
            }
            // 前置事件
            this.beforeScript(btn.getAlias(), (result) => {
              if (result) {
                return btn.action.apply(this, [btn])
              }
            })
          }
        }
        actions.push(button)
      })
      return actions
    },
    closeMoreAction() {
      this.$refs.frToolbar.closeMoreAction()
    },
    // 自定义按钮数据事件
    onLoadActions: function(key, button, type, defaultVal) {
      const buttonActionResult = JForm._onLoadActions(this, key, button, type)
      if (typeof (buttonActionResult) !== 'undefined' && buttonActionResult) {
        return true
      }
      return defaultVal
    },
    handleButtonEvent(button, position, data, index) {
      const action = this.actions.find((action) => {
        return button.key === action.key
      })
      if (action) {
        action.callback()
      }
    },
    handleActionEvent(actionKey, args = {}) {
      this.$emit('action-event', actionKey, args)
    },
    disabledStepButton(key) {
      if (key === 'prev') {
        return this.curActiveStep === 0
      } else {
        return this.stepNum - 1 === this.curActiveStep
      }
    },
    /** **Step 处理 */
    getStepButtons() {
      if (this.$utils.isEmpty(this.step)) {
        return []
      }
      if (this.$utils.isNotEmpty(this.step.field_options.buttons)) {
        return this.step.field_options.buttons
      } else {
        const defaultButtons = [
          {
            key: 'prev',
            icon: 'angle-left',
            label: '上一步'
          },
          {
            key: 'next',
            icon: 'angle-right',
            label: '下一步'
          }]
        return defaultButtons
      }
    },
    getFormStep() {
      const step = {}
      if (this.$utils.isEmpty(this.formDef)) {
        return
      }
      for (let i = 0; i < this.formDef.fields.length; i++) {
        const field = this.formDef.fields[i]
        if (field.field_type === 'steps') {
          return field
        }
      }
      return step
    },
    handleStepButtonEvent(button) {
      const key = button.key
      if (key === 'next' && this.curActiveStep === this.stepNum - 1) {
        ActionUtils.warning('没有更多')
        return
      }
      if (key === 'prev' && this.curActiveStep === 0) {
        ActionUtils.warning('没有上一步')
        return
      }
      this.stepLoading = true
      const curDate = new Date().getTime()
      let time = 0
      if (this.curTime + 1500 >= curDate) {
        time = 1000
      }
      this.curTime = curDate
      setTimeout(() => {
        if (key === 'next') {
          this.validate(valid => {
            if (valid) {
              this.curActiveStep++
            } else {
              this.formErrorToast()
            }
          })
        } else {
          this.curActiveStep--
        }
        this.stepLoading = false
      }, time)
    },
    callback() {
      this.$emit('callback')
    },
    closeDialog() {
      this.$emit('close')
    },
    getForm() {
      return this.$refs.dynamicForm
    },
    getFormValidator() {
      return this.getForm().getFormValidator()
    },
    /**
     * 获取表单验证
     */
    validate(callback) {
      this.getFormValidator().then(() => {
        callback(true)
      }).catch((e) => {
        if (e && e[0]) {
          this.getForm().scrollToField(e[0].name)
        }
        callback(false, e)
      })
    },
    formErrorToast(e) {
      this.$notify({
        type: 'warning',
        message: this.$t('common.formError')
      })
    },
    // 处理表单提交验证
    formSubmitVerify(callback) {
      if (!this.hasScript()) {
        if (callback) {
          this.getForm().formSubmitVerify(callback)
        }
        return
      }

      JForm._onValidate(this, (result, errorMsg) => {
        if (!result) {
          return callback(result, errorMsg || '验证不通过,请检查表单')
        }
        this.getForm().formSubmitVerify(callback)
      })
    },

    /**
     * 获取表单数据
     */
    getFormData() {
      return this.getForm().getFormData()
    },
    /**
     * 获取字段数据
     */
    getData(name) {
      const data = this.getFormData()
      return data[name]
    },
    /**
     * 设置字段数据
     */
    setData(name, value) {
      return this.getForm().setFieldData(name, value)
    },
    /**
     * 设置表单权限
     */
    getFormRights(name) {
      return this.getForm().getFormRights(name)
    },
    /**
     * 设置表单权限
     */
    setFormRights(name, value) {
      return this.getForm().setFormRights(name, value)
    },
    hasFormOpinion() {
      return this.getForm().hasFormOpinion()
    },
    /**
     * 表单意见数据
     */
    getFormOpinionData() {
      return this.getForm().getFormOpinionData()
    },
    /**
     * 获取审批意见验证
     */
    formOpinionValidate(calback, flag) {
      this.getForm().formOpinionValidate(calback, flag)
    },
    /**
     * 初始化脚本
     */
    initJForm() {
      let script = document.getElementById(JFormId)
      if (script) {
        script.parentNode.removeChild(script)
      }
      if (this.formDef.attrs && this.formDef.attrs.mobile_script) {
        const codeScript = this.formDef.attrs.mobile_script
        script = document.createElement('script')
        script.type = 'text/javascript'
        script.id = JFormId
        document.body.appendChild(script)
        try {
          script.appendChild(document.createTextNode(codeScript))
        } catch (ex) {
          console.error(ex)
          script.text = codeScript
        }
        document.body.appendChild(script)
      }
    },
    // 处理脚本
    hasScript() {
      return this.getForm().hasScript
    },
    // 加载脚本
    loadScript() {
      this.$emit('load', this)
      if (!this.hasScript()) {
        return
      }
      JForm._onLoad(this, this.getForm)
    },
    // 前置脚本
    beforeScript(action, callback) {
      if (!this.hasScript()) {
        if (callback) {
          const flag = true
          callback(flag)
        }
        return
      }
      JForm._beforeSubmit(this, action, this.getFormData(), callback)
    },
    // 后置脚本
    afterScript(action, params, callback) {
      this.formParams = params
      if (!this.hasScript()) {
        if (callback) {
          const flag = true
          callback(flag)
        }
        return
      }
      JForm._afterSubmit(this, action, this.getFormData(), callback)
    }
  }
}
</script>
