<template>
  <!--  自定义事件弹框  -->
  <a-modal
    title="事件编辑器"
    width="60%"
    :z-index="1001"
    :destroyOnClose="true"
    @ok="handleEventEditorOk"
    @cancel="handleEventEditorCancel"
    v-if="showEventEditor"
    :visible="showEventEditor">
    <a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }" v-if="showForm">
      <!--    事件触发类型    -->
      <a-form-item label="事件触发类型">
        <a-select @change="handleEventEditorTypeChange" :default-value="eventEditorContent.emitType">
          <a-select-option
            v-for="(eventType, eventTypeIndex) in editorPropertiesConfig.selfEvent"
            :key="eventTypeIndex"
            :value="eventType">
            {{ eventType }}
          </a-select-option>
          <a-select-option value="customEmitType">
            自定义触发类型
          </a-select-option>
          <a-select-option value="lifeCycle">
            生命周期函数
          </a-select-option>
        </a-select>
      </a-form-item>
      <!--    自定义事件触发类型    -->
      <a-form-item label="自定义事件触发名" v-if="eventEditorContent.emitType === 'customEmitType'">
        <a-input v-model="eventEditorContent.customEmitType"/>
      </a-form-item>
      <!--    事件类型    -->
      <a-form-item label="事件类型" v-if="eventEditorContent.emitType && eventEditorContent.emitType !== 'lifeCycle'">
        <a-select @change="handleEventEditorEventTypeChange" :default-value="eventEditorContent.eventType">
          <a-select-option value="runFunction">
            调用组件方法
          </a-select-option>
          <a-select-option value="changeProps">
            修改组件的Props
          </a-select-option>
          <a-select-option value="runLogic">
            发送后端请求
          </a-select-option>
          <a-select-option value="log">
            调试日志
          </a-select-option>
          <a-select-option value="showModal" v-if="this.config.page.filter(page => page.type === 'modal').length > 0">
            修改弹框可见
          </a-select-option>
          <a-select-option value="showDraw" v-if="this.config.page.filter(page => page.type === 'draw').length > 0">
            修改抽屉可见
          </a-select-option>
          <a-select-option value="customJSFunction" v-if="eventEditorContent.emitType !== 'lifeCycle'">
            自定义JS
          </a-select-option>
        </a-select>
      </a-form-item>
      <!--    生命周期函数    -->
      <a-form-item label="生命周期名" v-if="eventEditorContent.emitType === 'lifeCycle'">
        <a-select @change="handleEventEditorLifeCycleChange" :default-value="eventEditorContent.lifeCycle">
          <a-select-option value="created">
            created
          </a-select-option>
          <a-select-option value="beforeMount">
            beforeMount
          </a-select-option>
          <a-select-option value="mounted">
            mounted
          </a-select-option>
          <a-select-option value="beforeUpdate">
            beforeUpdate
          </a-select-option>
          <a-select-option value="updated">
            updated
          </a-select-option>
          <a-select-option value="beforeDestroy">
            beforeDestroy
          </a-select-option>
          <a-select-option value="destroyed">
            destroyed
          </a-select-option>
        </a-select>
      </a-form-item>
      <!--    修改弹框可见 or 修改抽屉可见    -->
      <a-form-item label="修改可见" v-if="eventEditorContent.eventType === 'showModal' || eventEditorContent.eventType === 'showDraw'">
        <a-radio-group v-model="eventEditorContent.visible" button-style="solid">
          <a-radio-button value="open">
            显示
          </a-radio-button>
          <a-radio-button value="close">
            隐藏
          </a-radio-button>
        </a-radio-group>
      </a-form-item>
      <!--    弹框容器ID    -->
      <a-form-item label="弹框容器ID" v-if="eventEditorContent.eventType === 'showModal'">
        <a-select v-model="eventEditorContent.containerId">
          <a-select-option
            v-for="(modal) in config.page.filter(page => page.type === 'modal')"
            :key="modal.id"
            :value="modal.id">
            弹框_{{ modal.id }}
          </a-select-option>
        </a-select>
      </a-form-item>
      <!--    抽屉容器ID    -->
      <a-form-item label="抽屉容器ID" v-if="eventEditorContent.eventType === 'showDraw'">
        <a-select v-model="eventEditorContent.containerId">
          <a-select-option
            v-for="(draw) in config.page.filter(page => page.type === 'draw')"
            :key="draw.id"
            :value="draw.id">
            抽屉_{{ draw.id }}
          </a-select-option>
        </a-select>
      </a-form-item>
      <!--    Logic名    -->
      <a-form-item label="后端Api" v-if="eventEditorContent.eventType === 'runLogic'">
        <a-input v-model="eventEditorContent.logicName"/>
      </a-form-item>
      <!--    自定义Logic参数    -->
      <a-form-item label="自定义Logic参数" v-if="eventEditorContent.eventType === 'runLogic'">
        <a-button type="primary" @click="openLogicParamJSEditor">
          打开编辑器
        </a-button>
      </a-form-item>
      <!--    自定义Logic回调    -->
      <a-form-item label="自定义Logic回调" v-if="eventEditorContent.eventType === 'runLogic'" >
        <a-button type="primary" @click="openLogicCallbackEditor">
          打开编辑器
        </a-button>
      </a-form-item>
      <!--    修改组件的值 才会显示的其余参数    -->
      <template v-if="eventEditorContent.eventType === 'runFunction' || eventEditorContent.eventType === 'changeProps' || eventEditorContent.eventType === 'customJSFunction'">
        <!--    目标组件    -->
        <a-form-item label="目标组件">
          <a-select @change="handleEventEditorTargetChange" :default-value="eventEditorContent.target">
            <a-select-option
              v-for="(targetId, targetIndex) in getAllRenderedComponents()"
              :key="targetIndex"
              :value="targetId">
              {{ targetId }}
            </a-select-option>
          </a-select>
        </a-form-item>
        <!--    目标组件执行事件    -->
        <a-form-item label="目标组件执行事件" v-if="eventEditorContent.eventType === 'runFunction' && eventEditorContent.target !== undefined">
          <a-select @change="handleEventEditorTargetEventTypeChange" :default-value="eventEditorContent.eventName">
            <a-select-option :value="eventType.name" v-for="(eventType,eventTypeIndex) in targetComponentMethods" :key="'eventType_' + eventTypeIndex">
              {{ eventType.str }}
            </a-select-option>
          </a-select>
          <p v-if="targetComponentEventDesc !== undefined">{{ targetComponentEventDesc }}</p>
        </a-form-item>
        <!--    目标组件修改值对应的key    -->
        <a-form-item label="对应的key" v-if="eventEditorContent.target !== undefined && eventEditorContent.eventType === 'changeProps'">
          <a-input v-model="eventEditorContent.targetKey"/>
        </a-form-item>
      </template>
      <!--    自定义执行方法的参数    -->
      <a-form-item label="自定义执行方法参数" v-if="eventEditorContent.eventType === 'runFunction'">
        <a-button type="primary" @click="openRunFunctionParamEditor">
          打开编辑器
        </a-button>
      </a-form-item>
      <!--    自定义JS方法    -->
      <a-form-item label="自定义JS方法" v-if="eventEditorContent.emitType !== 'lifeCycle' && eventEditorContent.eventType === 'customJSFunction'">
        <a-button type="primary" @click="openEventJSEditor">打开编辑器</a-button>
      </a-form-item>
      <!--    自定义钩子函数    -->
      <a-form-item label="自定义生命周期函数" v-if="eventEditorContent.emitType === 'lifeCycle'">
        <a-button type="primary" @click="openEventLifeCycleJSEditor">打开编辑器</a-button>
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script>
import * as lowcodeUtils from '@vue2-client/utils/lowcode/lowcodeUtils'

// 函数编辑器显示的模板
const JSEventFunctionTemplate = 'function(eventType, data, targetKey, sourceVM, targetVM) {\n  \n  return {\n    "eventType": eventType,\n    "data": data,\n    "targetKey": targetKey\n  }\n}'
const LogicParamFunctionTemplate = 'function(componentData, data) {\n  \n  return {\n    \n  }\n}'
const LogicCallBackFunctionTemplate = 'function(componentsMap, responseData) {\n  \n}'
const LifeCycleFunctionTemplate = 'function(vm) {\n  \n}'
const RunFunctionParamTemplate = 'function(vm, data) {\n\n  return [\n\n  ]\n}'

export default {
  name: 'LowCodeEventEditorModal',
  props: {
    // 用于保存右侧编辑组件的属性
    // eslint-disable-next-line vue/require-default-prop
    editorPropertiesConfig: {
      type: Object,
      require: true
    },
    // 用于事件编辑的回显，在点击事件编辑按钮后，会将此变量赋值
    eventEditorCurrent: {
      type: Object,
      default: undefined
    }
  },
  inject: [
    'componentsMap'
  ],
  data () {
    return {
      // 目标组件暴露出的事件
      targetComponentMethods: [],
      // 目标组件已选择的事件描述
      targetComponentEventDesc: undefined,
      // 控制事件编辑器弹框显隐
      showEventEditor: false,
      // 控制表单更新
      showForm: true
    }
  },
  methods: {
    changeVisible () {
      this.showEventEditor = !this.showEventEditor
    },
    changeOuterValue (key, value) {
      this.$emit('changeOuterValue', key, value)
    },
    // 事件编辑器点击完成
    handleEventEditorOk () {
      let emitTypeKey = this.eventEditorContent.emitType
      // 是否是自定义事件触发
      if (this.eventEditorContent.customEmitType) {
        emitTypeKey = this.eventEditorContent.customEmitType
      }
      // 如果当前是回显事件
      if (this.eventEditorCurrent) {
        const targetConfig = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
        targetConfig.onEvent[this.eventEditorCurrent.type][this.eventEditorCurrent.index] = { ...this.eventEditorContent }
      } else {
        // 当前是新增事件
        const target = lowcodeUtils.getComponentConfig(this.editorPropertiesConfig.id, this.config.page)
        // 如果没有onEvent属性则初始化
        if (!target.onEvent) {
          target.onEvent = {}
        }
        // 如果当前触发类型没有初始化，则初始化
        if (!target.onEvent[emitTypeKey]) {
          target.onEvent[emitTypeKey] = []
        }
        // 将缓存的事件属性赋值
        target.onEvent[emitTypeKey].push({
          ...this.eventEditorContent
        })
      }
      this.targetComponentMethods = []
      this.targetComponentEventDesc = undefined
      this.changeVisible()
      this.$store.commit('setEventEditorContent', {})
      this.$store.commit('setConfig', this.config)
      this.changeOuterValue('eventEditorCurrent', undefined)
      this.$emit('refresh', 'eventEditor')
    },
    // 关闭事件编辑器弹框
    handleEventEditorCancel () {
      this.targetComponentMethods = []
      this.targetComponentEventDesc = undefined
      this.changeVisible()
      this.$store.commit('setEventEditorContent', {})
      this.changeOuterValue('eventEditorCurrent', undefined)
    },
    // 事件编辑器中，触发类型改变
    handleEventEditorTypeChange (type) {
      this.$store.commit('setEventEditorContent', {})
      this.eventEditorContent.emitType = type
      this.refreshForm()
    },
    // 刷新表单
    refreshForm () {
      this.showForm = false
      this.$nextTick(() => {
        this.showForm = true
      })
    },
    // 事件编辑器中，目标组件改变
    handleEventEditorTargetChange (target) {
      this.targetComponentMethods = []
      this.eventEditorContent.target = target
      // 将目标组件暴露的方法，填入单选框
      const targetType = target.split('_')[0]
      const editorConfig = lowcodeUtils.getEditorConfigByType(targetType)
      if (editorConfig.selfMethods) {
        editorConfig.selfMethods.forEach(eachMethod => {
          // str用于下拉框中显示，包含函数名和形参
          const methodStr = eachMethod.name + '(' + eachMethod.params + ')'
          this.targetComponentMethods.push({
            str: methodStr,
            desc: eachMethod.desc,
            name: eachMethod.name
          })
        })
      }
      this.$forceUpdate()
    },
    handleEventEditorLifeCycleChange (lifeCycleName) {
      this.eventEditorContent.lifeCycle = lifeCycleName
    },
    // 事件编辑器中，事件类型改变
    handleEventEditorEventTypeChange (type) {
      const temp = {
        emitType: this.eventEditorContent.emitType
      }
      temp.eventType = type
      if (this.eventEditorContent.customEmitType) {
        temp.customEmitType = this.eventEditorContent.customEmitType
      }
      this.$store.commit('setEventEditorContent', temp)
      this.refreshForm()
    },
    // 事件编辑器中，目标组件执行事件类型改变
    handleEventEditorTargetEventTypeChange (type) {
      this.targetComponentMethods.forEach(eachMethod => {
        if (eachMethod.name === type) {
          this.targetComponentEventDesc = eachMethod.desc
        }
      })
      this.eventEditorContent.eventName = type
      this.$forceUpdate()
    },
    // 打开执行方法参数编辑弹框
    openRunFunctionParamEditor () {
      if (!this.eventEditorContent.runFunctionParam) {
        this.eventEditorContent.runFunctionParam = RunFunctionParamTemplate
      }
      this.$store.commit('setEventEditorContent', this.eventEditorContent)
      this.$emit('openModal', 'functionParam')
    },
    // 打开logic回调编辑弹框
    openLogicCallbackEditor () {
      if (!this.eventEditorContent.logicCallBackFunction) {
        this.eventEditorContent.logicCallBackFunction = LogicCallBackFunctionTemplate
      }
      this.$store.commit('setEventEditorContent', this.eventEditorContent)
      this.$emit('openModal', 'logicCallBack')
    },
    // 打开logic参数JS编辑器弹框
    openLogicParamJSEditor () {
      if (!this.eventEditorContent.logicParamJSFunction) {
        this.eventEditorContent.logicParamJSFunction = LogicParamFunctionTemplate
      }
      this.$store.commit('setEventEditorContent', this.eventEditorContent)
      this.$emit('openModal', 'logicParam')
    },
    // 打开JS函数编辑器
    openEventJSEditor () {
      if (!this.eventEditorContent.JSFunction) {
        this.eventEditorContent.JSFunction = JSEventFunctionTemplate
      }
      this.$store.commit('setEventEditorContent', this.eventEditorContent)
      this.$emit('openModal', 'customJS')
    },
    // 打开钩子函数编辑器
    openEventLifeCycleJSEditor () {
      if (!this.eventEditorContent.LifeCycleFunction) {
        this.eventEditorContent.LifeCycleFunction = LifeCycleFunctionTemplate
      }
      this.$store.commit('setEventEditorContent', this.eventEditorContent)
      this.$emit('openModal', 'lifeCycle')
    },
    // 获取所有注册组件
    getAllRenderedComponents () {
      const IDs = Object.keys(this.componentsMap)
      const result = []
      IDs.forEach(id => {
        const config = lowcodeUtils.getConfig(id, this.config)
        if (config.name) {
          result.push(config.name)
        } else {
          result.push(config.id)
        }
      })
      return result
    },
  },
  mounted () {
  },
  computed: {
    config () {
      return this.$store.state.lowCode.config
    },
    eventEditorContent () {
      return this.$store.state.lowCode.eventEditorContent
    }
  }
}
</script>

<style scoped lang="less">

</style>
