<template>
  <div class="template-select">
    <el-select
      :class="{select__block: !inline}"
      :model-value="modelValue"
      :placeholder="placeholder"
      :clearable="clearable"
      :disabled="disabled"
      :filterable="true"
      :filter-method="filterMethod"
      @change="handleChange"
      @update:modelValue="$emit('update:modelValue', $event)"
    >
      <el-option
        v-for="data in computedList"
        :key="data.id"
        :value="data.id"
        :label="data.name"
      />
    </el-select>
    <div v-if="settingTableData.length > 0" class="setting-wrap">
      <h3>设置模板参数</h3>
      <el-table :data="settingTableData" row-key="name">
        <el-table-column label="数据项" prop="label" width="100px"/>
        <el-table-column label="数据所需参数设置">
          <template #default="{ row }">
            <el-form :ref="`${row.name}ParameterForm`" :model="row.form" :rules="row.rules">
              <el-form-item
                v-for="parameter in row.parameters"
                :key="parameter.name"
                :label="parameter.label"
                :prop="parameter.name"
                :required="parameter.required"
              >
                <TemplateParameterInput
                  :type="parameter.component"
                  v-model="row.form[parameter.name]"
                  @change="emitUpdateParameters"
                />
                <FormItemTip v-if="!parameter.required">如不填写，需在获取模板数据时传入该参数！</FormItemTip>
              </el-form-item>
            </el-form>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import TemplateParameterInput from '@/components/cms/template/parameter-input'
import { fetchAll } from '@/api/cms/template'

export default {
  name: 'TemplateSelect',
  components: { TemplateParameterInput },
  props: {
    // 模板ID
    modelValue: {},
    // 模板参数
    parameters: {},
    disabled: {
      default: false
    },
    placeholder: {
      default: '请选择模板'
    },
    inline: {
      default: true
    },
    clearable: {
      default: true
    }
  },
  data () {
    return {
      filterWord: '',
      list: [],
      // 模板数据设置
      settingTableData: [],
      // 设置表单
      settingForm: {},
      // 设置表单规则
      settingRules: {}
    }
  },
  computed: {
    computedList () {
      if (this.filterWord.trim() === '') {
        return this.list
      }
      return this.list.filter(item => item.name.indexOf(this.filterWord) !== -1)
    }
  },
  methods: {
    // 过滤
    filterMethod (kwd) {
      this.filterWord = kwd
    },
    // 查询数据
    fetchList () {
      fetchAll()
        .then(data => {
          this.list = data
          // 构建数据项配置参数表格
          this.buildSettingTable(this.modelValue)
          // 初始化数据项配置参数值
          this.initSettingValues(this.parameters)
        })
        .catch(e => {
          this.$tip.apiFailed(e)
        })
    },
    // 处理change事件
    handleChange (evt) {
      this.buildSettingTable(evt)
      this.$emit('change', evt)
      this.emitUpdateParameters()
    },
    /**
     * 构建参数设置表
     * 1. 获取模板所需的数据项编码集
     * 2. 循环数据项编码集，根据编码从字典中取出各个数据项的参数配置
     * 3. 将编码和参数配置构建成对象写入settingTableData中
     *
     * @param templateId 模板唯一标识
     * @returns {null}
     */
    buildSettingTable (templateId) {
      if (templateId == null) {
        this.settingTableData = []
        return
      }
      const template = this.list.find(item => item.id === templateId)
      // 1. 获取模板所需的数据项编码集
      const dataCodes = template.presetDataCodes == null || template.presetDataCodes.trim() === '' ?
        [] : template.presetDataCodes
          .split(',')
          .filter(item => item.trim() !== '')
      // - 模板未配置任何数据项，无需设置参数
      if (dataCodes == null || dataCodes.length === 0) {
        this.settingTableData = []
        return
      }

      // 2. 循环数据项编码集，根据编码从字典中取出各个数据项的参数配置
      this.settingTableData = dataCodes
        .map(dataCode => {
          // 2.1 从字典中获取到当前数据项的参数列表
          let dictDataConfig = this.$dc(`TEMPLATE_DATA_LIST.${dataCode}`)
          if (dictDataConfig == null || dictDataConfig === '') {
            return null
          }
          dictDataConfig = JSON.parse(dictDataConfig)
          const dataItemParameters = dictDataConfig.parameters
          // 2.2 根据数据项所需参数，构建参数列表和参数值表单
          const parameters = []
          const form = {}
          const rules = {}
          // - dataItemParameter: { name: 参数名, label: 参数显示名称, component: 参数输入组件名称, required: 是否必填 }
          for (const dataItemParameter of dataItemParameters) {
            parameters.push(dataItemParameter)
            // 配置值设置为空
            form[dataItemParameter.name] = null
            // 必填项
            if (dataItemParameter.required) {
              rules[dataItemParameter.name] = [
                { required: true, message: `${dataItemParameter.label}不能为空` }
              ]
            }
          }
          if (parameters.length === 0) {
            return null
          }
          // 2.3 组装数据项的参数配置列表
          return {
            name: dataCode,
            label: this.$d(`TEMPLATE_DATA_LIST.${dataCode}`),
            parameters,
            form,
            rules
          }
        })
        .filter(item => item != null)
    },
    /**
     * 初始化设置值
     *
     * @param parameters 预设数据的参数
     */
    initSettingValues (parameters) {
      for (const dataItem in parameters) {
        const targetSettingRow = this.settingTableData.find(item => item.name === dataItem)
        if (targetSettingRow == null) {
          continue
        }
        const dataItemParameters = parameters[dataItem]
        for (const p of dataItemParameters) {
          targetSettingRow.form[p.name] = p.value
        }
      }
    },
    // 触发参数更新
    emitUpdateParameters () {
      if (this.settingTableData.length === 0) {
        this.$emit('update:parameters', null)
        return
      }
      const parameters = {}
      for (const dataItem of this.settingTableData) {
        parameters[dataItem.name] = dataItem.parameters.map(parameter => {
          return {
            name: parameter.name,
            value: dataItem.form[parameter.name]
          }
        })
      }
      this.$emit('update:parameters', parameters)
    },
    // 验证表单
    validateForm () {
      const validatePromises = []
      for (const dateItem of this.settingTableData) {
        validatePromises.push(this.$refs[`${dateItem.name}ParameterForm`].validate())
      }
      return Promise.all(validatePromises)
    }
  },
  created () {
    this.fetchList()
  }
}
</script>
<style lang="scss" scoped>
.template-select {
  & > .el-select {
    display: block;
  }
  .setting-wrap {
    padding: 10px 20px;
    background-color: var(--background-color);
    h3 {
      font-weight: normal;
      font-size: var(--font-size);
    }
    .el-form-item {
      margin-bottom: 18px;
    }
  }
}
</style>
