<template>
  <a-spin :spinning="loading" :class="$style.spin">
    <sd-form ref="form" :init-values="fields">
      <template v-slot="{ model }">
        <table class="sd-form-table">
          <tr v-for="field in fields" v-show="!field.sdHidden" :key="field.name">
            <sd-form-item-td
              :name="field.name"
              :input-props="field.attrFD?.formItemProps?.inputProps || {}"
            >
              <!-- 关联数据 -->
              <a-select
                v-if="field.name === 'associateData'"
                v-model="model[field.name]"
                :options="field.attr.selectListItem"
                @change="associateDataChange"
              />
              <!-- 事件类型 -->
              <a-select
                v-if="field.name === 'methodType'"
                v-model="model.methodType"
                :options="eventOptions"
                @change="methodTypeChange"
              />
            </sd-form-item-td>
          </tr>
        </table>
      </template>
    </sd-form>
    <component
      :is="eventComponents[eventType]"
      v-if="!!eventType"
      ref="eventProps"
      :data-source="eventScript"
    />
  </a-spin>
</template>

<script>
import eventHandlers from './event-handlers'
import components from './_import-components/sd-events-frontend-form-import'

export default {
  name: 'SdEventsFrontendForm',
  components,
  props: {
    eventsDefine: {
      type: Object,
      default: () => {},
    },
    formData: {
      type: Object,
      default: undefined,
    },
  },
  inject: {
    SdEventsManage: { default: () => {} },
  },
  data() {
    return {
      eventType: '',
      eventScript: {},
      fields: [
        {
          name: 'methodName',
          caption: '事件名称',
          dataType: 'string',
          required: true,
        },
        {
          name: 'methodCode',
          caption: '事件编码',
          dataType: 'string',
          required: true,
          attr: {
            regex: /^[a-z][a-zA-Z]*$/,
            regexMessage: '必须是字母,建议为驼峰格式，如createFlow',
          },
          attrFD: {
            formItemProps: {
              inputProps: {
                placeholder: '请输入字母，建议为驼峰格式，如createFlow',
              },
            },
          },
        },
        {
          name: 'methodDesc',
          caption: '事件说明',
          dataType: 'string',
        },
        {
          name: 'sortNumber',
          caption: '排序号',
          dataType: 'number',
          attr: {
            controlType: 'NumberType',
            decimalPrecision: '0',
            field: 'sortNumber',
            mandatory: 'false',
            maxValue: '99999',
            minValue: '0',
          },
        },
        {
          name: 'associateData',
          caption: '关联数据',
          dataType: 'selectlist',
          required: true,
          attr: {
            defaultValue: 'single',
            selectListItem: [
              { label: '无', value: 'none' },
              { label: '单个', value: 'single' },
              { label: '多个', value: 'multiple' },
            ],
          },
          attrFD: {
            popoverDescription: true,
            description:
              '<div>当前事件是否与数据有关：</div>' +
              '<div><b>无</b>：与数据无关，如列表上的普通按钮（导入等），点击后执行的操作无需与某数据关联</div>' +
              '<div><b>单个</b>：与一条数据有关，如列表的行内按钮，点击后执行的操作与当前行的数据相关</div>' +
              '<div><b>多个</b>：与多条数据有关，如列表的批量按钮，点击后需操作多条数据</div>',
          },
        },
        {
          name: 'methodType',
          caption: '事件类型',
          dataType: 'string',
          required: true,
        },
      ],
      associateData: '',
      loading: true,
    }
  },
  computed: {
    eventComponents() {
      const component = {}
      this.eventsDefine[this.associateData]?.forEach((e) => {
        component[e.id] = e.module.default
      })
      return component
    },
    eventOptions() {
      return (
        this.eventsDefine[this.associateData]?.map((e) => ({
          label: e.module.metaInfo?.name,
          value: e.id,
        })) || []
      )
    },
  },
  created() {
    this.initForm()
    if (this.formData?.associateData) {
      this.associateData = this.formData?.associateData
    } else {
      // 当前是新建事件：获取[关联数据]的默认值
      const field = this.fields.find((f) => f.name === 'associateData')
      // 有默认值是，赋值
      if (field?.attr?.defaultValue) {
        this.associateData = field.attr.defaultValue
      }
    }
    // 有选择[关联数据]，加载对应的事件定义
    if (this.associateData) {
      this.loadEventsDefine(this.associateData).then(() => {
        this.loading = false
      })
    } else {
      this.loading = false
    }
  },
  methods: {
    validate() {
      return Promise.all([
        this.$refs.form.validateFields() ?? true,
        this.$refs.eventProps.validate?.() ?? true,
      ]).then((flags) => {
        return flags.every((f) => f)
      })
    },
    initForm() {
      if (this.formData) {
        this.fields?.forEach((f) => {
          if (f.name === 'methodType') {
            f.value = this.formData.methodScript?.[0]?.methodType
            this.eventType = f.value
          } else {
            f.value = this.formData[f.name]
          }
        })
        this.eventScript = this.formData.methodScript[0] || {}
      }
    },
    methodTypeChange(value) {
      this.eventType = value
      this.eventScript =
        this.formData?.methodScript?.find((m) => m.methodType === this.eventType) || {}
    },
    getSaveData() {
      const formData = {}
      this.$refs.form.getBackendValues().forEach((item) => {
        // 去除(无需保存)：事件类型
        if (item.name !== 'methodType') {
          formData[item.name] = item.value
        }
      })
      this.eventScript.methodType = this.eventType
      formData.methodScript = [this.eventScript]
      return formData
    },
    loadEventsDefine(associateData) {
      if (!this.eventsDefine[associateData]?.length) {
        return eventHandlers.loadFrontEnd(associateData).then((events) => {
          // 加载的事件定义存储至事件管理页面，避免新建事件、查看事件时重复加载事件定义
          this.$set(this.eventsDefine, associateData, events)
        })
      }
      return Promise.resolve()
    },
    associateDataChange(value) {
      // 清空事件类型的选择
      this.$refs.form.setFieldValue('methodType', undefined)
      this.eventType = ''
      this.eventScript = {}
      this.associateData = value
      this.loadEventsDefine(value)
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.label {
  display: inline-block;
}
.spin {
  width: 100%;
}
</style>
