<template>
  <div class="ibps-fixed-top">
    <template v-if="formModel.type === 'INNER'">
      <!---在线表单--->
      <formrender
        v-if="formDef"
        ref="formrender"
        :form-def="formDef"
        :buttons="buttons"
        :data="formData"
        :params="formParams"
        :readonly="readonly"
        @action-event="(actionKey,args)=>emitEventHandler(actionKey,args)"
        @callback="callbackPage"
        @close="closeDialog"
      />
    </template>
    <!---内嵌url表单,外部url表单---->
    <template
      v-else-if="formModel.type === 'URL_LOAD'|| formModel.type === 'FRAME'"
    >
      <form-toolbar
        v-if="formModel.type === 'URL_LOAD'"
        :buttons="buttons"
        :validate-form="validateForm"
        :on-load-actions="onLoadActions"
        :before-script="beforeScript"
        :after-script="afterScript"
        @action-event="(actionKey,args)=>emitButtonEventHandler(actionKey,args)"
        @callback="callbackPage"
        @close="closeDialog"
      />

      <!--url表单 iframe方式-->
      <iframe
        v-if="formUrlType === 'iframe'"
        ref="formrender"
        :class="formModel.type === 'URL_LOAD'?'ibps-container-url-frame':'ibps-container-frame'"
        frameborder="0"
      />
      <!--url表单 vue组件方式-->
      <template v-else>
        <component
          :is="formUrlName"
          v-if="!loading"
          ref="formrender"
          :params="formParams"
          :readonly="readonly"
          @action-event="(actionKey,args)=>emitButtonEventHandler(actionKey,args)"
          @callback="callbackPage"
          @close="closeDialog"
        />
      </template>
    </template>

    <!--流程图-->
    <flow-diagram-dialog
      :visible="flowDiagramVisible"
      :def-id="defId"
      :task-id="taskId"
      :inst-id="instId"
      @close="visible => flowDiagramVisible= visible"
    />
    <!--流程历史-->
    <approval-history-dialog
      :visible="approvalHistoryVisible"
      :task-id="taskId"
      :inst-id="instId"
      @close="visible => approvalHistoryVisible= visible"
    />
    <!--流程实例-->
    <!-- <instance-detail
      :visible="instanceDetailVisible"
      :bpmn-inst-id="instId"
      @close="visible => instanceDetailVisible= visible"
    /> -->

    <!--启动流程-->
    <start-flow-dialog
      :visible="startFlowDialogVisible"
      :def-id="defId"
      :data="submitFormData"
      :title="actionTitle"
      @close="visible => startFlowDialogVisible= visible"
      @action-event="saveStartFlow"
    />

    <!--同意-->
    <agree-dialog
      :visible="agreeDialogVisible"
      :action="actionName"
      :title="actionTitle"
      :task-id="taskId"
      :version="version"
      :is-common="attributes.isCommonJumpType"
      :hide-opinion="isBpmOpinionHide"
      :hide-path="attributes.isHidePath"
      :form-opinion="submitFormOpinion"
      @close="visible => agreeDialogVisible= visible"
      @action-event="handleActionEvent"
    />

    <!--驳回-->
    <reject-dialog
      :visible="rejectDialogVisible"
      :action="actionName"
      :title="actionTitle"
      :task-id="taskId"
      :hide-opinion="isBpmOpinionHide"
      :form-opinion="submitFormOpinion"
      @close="visible => rejectDialogVisible= visible"
      @action-event="handleActionEvent"
    />
    <!--终止流程-->
    <approve-dialog
      :visible="approveDialogVisible"
      :action="actionName"
      :title="actionTitle"
      :task-id="taskId"
      :hide-opinion="isBpmOpinionHide"
      :form-opinion="submitFormOpinion"
      callback-event
      @close="visible => approveDialogVisible= visible"
      @action-event="handleActionEvent"
    />
    <!--转办-->
    <delegate-dialog
      :id="taskChangeId"
      :visible="delegateDialogVisible"
      :action="actionName"
      :title="actionTitle"
      :task-id="taskId"
      :readonly="delegateReadonly"
      @close="visible => delegateDialogVisible= visible"
      @callback="callbackPage"
    />
    <!--任务补签-->
    <add-sign-task-dialog
      :visible="addSignTaskDialogVisible"
      :action="actionName"
      :title="actionTitle"
      :task-id="taskId"
      :hide-opinion="false"
      :form-opinion="submitFormOpinion"
      @close="visible => addSignTaskDialogVisible= visible"
      @action-event="handleActionEvent"
      @callback="callbackPage"
    />
  </div>
</template>
<script>
import { getFormData, getInstFormData } from '@/api/platform/bpmn/bpmInst'
import { getTaskFormData } from '@/api/platform/bpmn/bpmTask'
import FormUtil from '@/business/platform/form/utils/formUtil'
import ActionMixin from './action'
import BpmnButton from './button'
import RouteLeaveMixin from '@/mixins/routeLeave'// 表单未保存提示

import Formrender from '@/business/platform/form/formrender'
import FormToolbar from '@/business/platform/form/formrender/toolbar'

import FlowDiagramDialog from '@/business/platform/bpmn/components/flow-diagram/dialog'
import ApprovalHistoryDialog from '@/business/platform/bpmn/components/approval-history/dialog'

import StartFlowDialog from '../form-ext/start-flow'
import ApproveDialog from '../form-ext/approve'
import AgreeDialog from '../form-ext/agree'
import RejectDialog from '../form-ext/reject'
import DelegateDialog from '../form-ext/delegate'
import AddSignTaskDialog from '../form-ext/addSignTask'

const _import = require('@/utils/util.import.' + process.env.NODE_ENV)

export default {
  components: {
    Formrender,
    FormToolbar,
    FlowDiagramDialog,
    ApprovalHistoryDialog,

    StartFlowDialog,
    ApproveDialog,
    AgreeDialog,
    RejectDialog,
    DelegateDialog,
    AddSignTaskDialog
  },
  mixins: [
    ActionMixin,
    RouteLeaveMixin
  ],
  props: {
    defId: { // 流程定义ID
      type: String
    },
    proInstId: { // 草稿流程实例ID
      type: String
    },
    instId: { // 流程实例ID
      type: String
    },
    taskId: { // 流程任务ID
      type: String
    },
    taskChangeId: { // 转办代理任务ID
      type: String
    },
    copyFlow: { // 是否复制流程
      type: Boolean,
      default: false
    },
    closeable: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      isRoute: false,

      flowDiagramVisible: false, // 流程图
      approvalHistoryVisible: false,
      instanceDetailVisible: false,
      startFlowDialogVisible: false,
      agreeDialogVisible: false, // 同意
      rejectDialogVisible: false, // 驳回
      delegateDialogVisible: false,
      addSignTaskDialogVisible: false,
      approveDialogVisible: false,

      delegateReadonly: false,

      endProcessTaskId: '',

      actionName: '',
      actionTitle: '',
      version: 0,
      // ========表单的数据=======
      loading: false,
      formUrlName: '',
      formUrlType: 'inner', // 内嵌url方式：inner： vue组件方式，iframe：iframe方式

      formModel: {
        type: 'INNER'
      },
      formDef: null,
      buttons: [],
      formData: {},
      attributes: {}, // 新增扩展属性
      formParams: {}, // 表单流程扩展参数
      isBpmOpinionHide: false,
      readonly: false,

      submitFormData: {},
      submitFormOpinion: ''
    }
  },

  // created() {
  //   const query = this.$route.query
  //   this.defId = query.defId // 流程定义
  //   this.proInstId = query.proInstId // 草稿启动的流程实例id
  //   this.taskId = query.taskId//  任务ID
  //   this.instId = query.instId// 任务实例ID
  //   this.nodeId = query.nodeId// 节点ID
  //   this.taskChangeId = query.taskChangeId // 转办ID

  //   this.title = this.$route.params.title || ''// 标题

  //   this.loadFormData()
  // },
  methods: {
    // 获取数据
    loadFormData() {
      this.loading = true
      this.formDef = null
      this.buttons = null
      this.formData = null
      this.$nextTick(() => {
        this.readonly = false
        if (this.$utils.isNotEmpty(this.taskId)) { // 处理流程任务
          this.getTaskFormData()
        } else if (this.$utils.isNotEmpty(this.defId)) { // 启动 或者草稿流程启动
          this.getDefinitionFormData()
        } else if (this.$utils.isNotEmpty(this.instId)) { // 流程实例
          this.getInstanceFormData()
        } else {
          this.$dialog.alert({
            message: '未获取正确的参数，请检查传入参数'
          }).then(() => {
            this.closeDialog()
          })
          this.loading = false
        }
      })
    },

    /**
     * 启动 或者草稿流程
     */
    getDefinitionFormData() {
      this.formParams.defId = this.defId
      this.formParams.proInstId = this.proInstId || null
      this.formParams.copyFlow = this.copyFlow
      getFormData({
        defId: this.defId,
        proInstId: this.proInstId || null
      }).then(response => {
        this.loading = false
        this.buildFormData(response.data)
      }).catch(() => {
        this.loading = false
      })
    },
    /**
     * 获取流程任务表单
     */
    getTaskFormData() {
      this.loading = true
      this.formParams.taskId = this.taskId || null
      getTaskFormData({
        taskId: this.taskId
      }).then(response => {
        this.loading = false
        this.buildFormData(response.data)
      }).catch(() => {
        this.loading = false
      })
    },
    /**
     * 流程实例 的表单数据
     */
    getInstanceFormData() {
      this.readonly = true
      this.formParams.instId = this.instId || null
      getInstFormData({
        instId: this.instId
      }).then(response => {
        this.loading = false
        this.buildFormData(response.data)
      }).catch(() => {
        this.loading = false
      })
    },
    /**
     * 构建表单相关数据
     */
    buildFormData(data) {
      if (this.$utils.isEmpty(data)) {
        this.$dialog.alert({
          message: `未获取到数据`
        }).then(() => {
          this.closeDialog()
        })
        return
      }
      const formModel = data.formModel
      this.formUrlType = 'inner'

      // 判断是否设置表单
      if (this.$utils.isEmpty(formModel)) {
        this.$dialog.alert({
          message: `未设置表单,请流程定义中设置表单`
        }).then(() => {
          this.closeDialog()
        })
        return
      }
      this.formModel = formModel
      // ============在线表单 ================
      if (formModel.type === 'INNER') {
        if (this.$utils.isEmpty(formModel.formData)) {
          this.$dialog.alert({
            message: `未设置在线表单`
          }).then(() => {
            this.closeDialog()
          })
        }
        // this.title = this.$utils.isEmpty(this.title) ? data.title : this.title

        // 表单定义
        this.formDef = this.$utils.parseData(formModel.formData) || {}

        this.formData = {
        // 表单数据
          responses: this.$utils.parseData(data.boData) || {},
          // 表单权限
          permissions: this.$utils.parseData(data.permissions) || {}
        }

        // 一些参数
        this.attributes = this.initAttributes(data)
        this.formParams.nodeId = this.attributes.nodeId
        // 操作按钮
        this.buttons = this.buildButtons(data.buttons, this.attributes) || []
        // 表单意见
        this.formParams.formOpinionData = FormUtil.initFormOpinionData(data.attributes || {})

        // 表单意见是否隐藏意见
        this.$nextTick(() => {
          this.isBpmOpinionHide = this.handleBpmOpinionHide(data.attributes || {})
        })
        // 流程关联信息
        this.formParams.bpmLinkData = FormUtil.getBpmLinkData(data.attributes || {})
        // 版本号
        this.version = data.version
        // 设置标题
        this.$store.dispatch('ibps/app/setTitle', this.title)
        // 设置数据是否改变
        this.$store.dispatch('ibps/app/setDataChange', false)

        // 流程实例当前审批节点
        this.endProcessTaskId = data.endProcessTaskId

      //  ============内嵌表单[按钮这边提供] ================
      } else if (formModel.type === 'URL_LOAD') {
        const urlForm = formModel.mobileValue
        if (this.$utils.isEmpty(urlForm)) {
          this.$dialog.alert({
            message: `未设置内嵌表单`
          }).then(() => {
            this.closeDialog()
          })
        }
        // 一些参数
        this.attributes = this.initAttributes(data)
        this.formParams.nodeId = this.attributes.nodeId
        // 操作按钮
        this.buttons = this.buildButtons(data.buttons, this.attributes) || []
        // 初始化url表单
        this.initUrlForm(urlForm)
      //  ============外部表单【iframe】 ================
      } else if (formModel.type === 'FRAME') {
        const urlForm = formModel.mobileValue
        if (this.$utils.isEmpty(urlForm)) {
          this.$dialog.alert({
            message: `未设置外部表单`
          }).then(() => {
            this.closeDialog()
          })
        }
        // 初始化url表单
        this.initUrlForm(urlForm)
      }
    },
    // 初始化url表单
    initUrlForm(url) {
      if (url.startsWith('http')) {
        this.formUrlType = 'iframe'
        this.$nextTick(() => {
          this.$refs.formrender.src = url
          // 传递消息
          this.$refs.formrender.contentWindow.postMessage({ data: this.attributes }, '*')
        })
      } else {
        const component = url.split('?')[0]
        this.formParams.attrs = this.urlParse(url)
        this.formUrlType = 'inner'
        const formUrlName = 'IbpsBpmnFormUrl'
        this.$options.components[formUrlName] = _import(component)
        this.formUrlName = formUrlName
      }
    },
    urlParse(str) {
      const obj = {}
      if (str.indexOf('?') !== -1) {
        const str1 = str.split('?')[1].split('&')
        for (let i = 0; i < str1.length; i++) {
          const params = str1[i].split('=')
          obj[params[0]] = params[1]
        }
      }
      return obj
    },
    initAttributes(data) {
      const attributes = data.attributes || {}
      return {
        title: this.title,
        defId: this.defId,
        proInstId: this.proInstId,
        taskId: this.taskId,
        nodeId: attributes.nodeId,
        lockUser: attributes.lockUser,
        // 当前用户
        curUserId: attributes.curUserId,
        // 挂起状态
        suspendState: attributes.suspendState,
        // 是否转办
        isHiddenDelegate: this.$utils.toBoolean(attributes.isHiddenDelegate),
        // 是否正常跳转
        isCommonJumpType: this.$utils.toBoolean(attributes.isCommonJumpType),
        // 是否隐藏意见
        isHideOpinion: this.$utils.toBoolean(attributes.isHideOpinion),
        // 是否隐藏路径
        isHidePath: this.$utils.toBoolean(attributes.isHidePath),
        // 是否结束
        isEnd: this.$utils.toBoolean(attributes.isEnd),
        // 第一个节点是否选择
        firstNodeUserAssign: attributes.firstNodeUserAssign,
        // 打印模版
        printTemplateId: data.formModel.templateId,
        // BO版本号
        version: data.version
      }
    },
    handleBpmOpinionHide(attributes = {}) {
      const formOpinionSetting = attributes.formOpinionSetting
      const nodeId = attributes.nodeId
      if (this.$utils.isNotEmpty(formOpinionSetting)) {
        let flag = false
        for (const o in formOpinionSetting) {
          const formOpinionHidden = formOpinionSetting[o]
          try {
            if (this.$utils.parseJSON(o).includes(nodeId)) {
              flag = this.$utils.toBoolean(formOpinionHidden)
              break
            }
          } catch (err) {
            console.error(err)
          }
        }
        return this.hasFormOpinion() && !flag ? flag : true
      }
      if (this.hasFormOpinion()) {
        return true
      }
      // 是否有表单意见
      return this.attributes.isHideOpinion || false
    },
    /**
     * 构建操作按钮
     */
    buildButtons(buttons, params) {
      if (this.$utils.isEmpty(buttons)) {
        buttons = []
      }
      // 如果转办，代理不为空
      if (this.$utils.isNotEmpty(this.taskChangeId)) {
        buttons.unshift({
          alias: 'delegateDetail',
          name: '转办/代理明细'
        })
      }
      const btns = []
      for (let i = 0; i < buttons.length; i++) {
        const button = buttons[i]
        const alias = button.alias
        const code = button.code
        button.key = alias === 'custom' ? (code || (alias + i)) : alias
        btns.push(button)
      }
      const btn = new BpmnButton({
        buttons: btns,
        params: params
      })
      return btn.response_buttons
    },
    getFormEL() {
      if (this.formUrlType === 'inner') {
        return this.$refs.formrender
      } else {
        try {
          // 跨域获取表单数据
          return this.$refs.formrender.contentWindow.ibpsFormUrl
        } catch (err) {
          console.error(err)
        }
      }
    },
    // 获取表单数据
    getFormData() {
      if (!(this.getFormEL() && this.getFormEL().getFormData)) {
        this.$toast('URL表单必须包含获取表单数据的方法【getFormData】')
        return
      }
      return this.getFormEL().getFormData()
    },
    // 是否有审批意见字段
    hasFormOpinion() {
      if (!(this.getFormEL() && this.getFormEL().hasFormOpinion)) {
        return false
      }
      return this.getFormEL().hasFormOpinion() || false
    },
    // 获取表单意见数据
    getFormOpinionData() {
      if (!(this.getFormEL() && this.getFormEL().getFormOpinionData)) {
        return ''
      }
      const formOpinionData = this.getFormEL().getFormOpinionData()
      let data = ''
      if (this.$utils.isEmpty(formOpinionData)) {
        return data
      }
      // 如果只有一个，多个，取最后一个
      for (const key in formOpinionData) {
        data = formOpinionData[key]
      }
      return data
    },
    onLoadActions() {
      return false
    },
    // 前置事件
    beforeScript(key, callback) {
      if (!(this.getFormEL() && this.getFormEL().beforeScript)) {
        const flag = true
        callback(flag)
        return
      }
      return this.getFormEL().beforeScript(key, callback)
    },
    // 后置事件
    afterScript(key, params, callback) {
      if (!(this.getFormEL() && this.getFormEL().afterScript)) {
        const flag = true
        callback(flag)
        return
      }
      return this.getFormEL().afterScript(key, params, callback)
    },
    // 回调上一个页面
    callbackPage() {
      if (!this.isRoute) {
        this.closeDialog()
      }
      this.$emit('callback', this)
    },
    // 关闭当前窗口
    closeDialog() {
      if (this.isRoute) {
        this.$router.go(-1)
      } else {
        this.$emit('close', this)
      }
    },
    // 跳转页面
    jumpPage(path, reload = false) {
      if (!this.isRoute) {
        return
      }
      if (reload) {
        this.$router.push({ path: '/refresh' })
      } else {
        setTimeout(() => {
          this.$router.push({ path: `/bpmn/${path}/index` })
        }, 1000)
      }
    },
    // 验证表单if
    validateForm(callback) {
      if (!(this.getFormEL() && this.getFormEL().validate)) {
        const flag = true
        callback(flag)
        return
      }
      this.getFormEL().validate().then(() => {
        callback(true)
      }).catch((valid) => {
        callback(false)
        this.$notify({
          type: 'warning',
          message: this.$t('common.formError')
        })
      })
    },
    isDraft: function() {
      return this.$utils.isNotEmpty(this.proInstId)
    }
  }
}
</script>
<style lang="scss" scoped>
  .ibps-container-frame {
      position: absolute;
      top: 0px;
      left: 0px;
      height: 100%;
      width: 100%;
  }
  .ibps-container-url-frame{
    position: absolute;
    top: 0px;
    left: 0px;
    width: 100%;
    height: calc(100vh - 50px) !important;
    margin-top: 50px;
  }
</style>
