<template>
	<el-dialog class="super-flexible-dialog" :title="isDetail ? title.detail : !dataForm.id ? title.add : title.edit" :visible.sync="visible" @close="handleClose">
		<el-form ref="dataForm" :model="dataForm" :rules="dataFormRules">
			<!-- 如果需要更精细一点的布局，可以根据配置项实现地再复杂一点，但此处暂时全部采用一行两列布局  -->
			<el-row v-for="n in rows" :key="n" :gutter="20">
				<el-col v-for="c in COLUMN_PER_ROW" :key="`${n}+'col'+${c}`" :span="24 / COLUMN_PER_ROW">
					<el-form-item
						v-if="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]"
						:prop="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name"
						:key="`${n}-col-${c}-item`"
						:label="getLabel(n, c)"
					>
						<!-- 暂时先不实现部分输入方式 -->
						<el-input
							v-if="getType(n, c) === 'input'"
							:placeholder="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].placeholder || '...'"
							v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
							clearable
						/>
						<el-radio v-if="getType(n, c) === 'radio'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-radio>
						<el-checkbox v-if="getType(n, c) === 'check'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-checkbox>
						<el-select
							v-if="getType(n, c) === 'select'"
							:placeholder="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].placeholder || ''"
							v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"
							clearable
						>
							<el-option v-for="opt in configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].options" :key="opt.label" :value="opt.value" />
						</el-select>
						<el-switch v-if="getType(n, c) === 'switch'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-switch>
						<el-cascader v-if="getType(n, c) === 'tree'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-cascader>
						<el-time-select v-if="getType(n, c) === 'time'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-time-select>
						<el-date-picker v-if="getType(n, c) === 'date'" v-model="dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]"></el-date-picker>
					</el-form-item>
				</el-col>
			</el-row>

			<!-- extra components , like Markdown or RichEdit -->
			<template v-if="configs.extraComponents && configs.extraComponents.length > 0">
				<el-form-item v-for="ec in configs.extraComponents" :key="ec.name" :label="ec.label">
					<component :is="ec.component" v-model="dataForm[ec.name]"></component>
				</el-form-item>
			</template>
		</el-form>

		<span slot="footer" class="dialog-footer">
			<template v-for="(operate, index) in configs.operations">
				<!-- {{ operate.name | btnNameFilter }} -->
				<el-button v-if="operate.permission ? $hasPermission(operate.permission) : true" :key="`operate-${index}`" :type="btnType[operate.name]" @click="handleClick(operate)">{{
					btnName[operate.name]
				}}</el-button>
			</template>
		</span>
	</el-dialog>
</template>

<script>
// 标题 for i18n
const title = {
	detail: '详情',
	add: '新增',
	edit: '编辑'
}

// 或者也可以改造成自定义颜色：
const btnType = {
	save: 'success',
	update: 'primary',
	reset: 'text'
	// add more...
}

const btnName = {
	// for i18n
	save: '保存',
	update: '更新',
	reset: '重置'
	// add more...
}

// 每行的列数
const COLUMN_PER_ROW = 2

export default {
	name: 'AddOrUpdateDialog',
	props: {
		configs: {
			/**
			 * type: 'dialog' | 'drawer' | 'page'
			 * fields: Array<string|object>
			 * - fields.object: { name, type: 'number'|'textarea'|'select'|'date'|.., required: boolean,  validator: boolean(是否需要验证), [options]: any[], api: string(自动获取数据的接口，一般为getcode接口)}
			 * operations: Array[object], 操作名和对应的接口地址，还有permission(如，sys:dict:update)
			 */
			type: Object,
			default: () => ({}) // 此处省去类型检查，使用者自行注意就好
		}
	},
	filters: {
		nameFilter: function(name) {
			if (!name) return null
			// for i18n
			const defaultNames = {
				name: '名称',
				code: '编码',
				remark: '备注',
				specifications: '规格'
				// add more...
			}

			return defaultNames[name]
		}
	},
	data() {
		return {
			COLUMN_PER_ROW,
			title,
			btnName,
			btnType,
			visible: false,
			isEdit: false,
			isDetail: false,
			// cached: false // 不采用缓存比较的方案了，采用 updated 方案： 如果更新了dataForm就在 confirm 时 emit(refreshDataList)
			isUpdated: false,
			dataForm: {},
			dataFormRules: {},
			defaultNames: {
				name: '名称',
				code: '编码',
				remark: '备注',
				specifications: '规格'
				// add more...
			}
		}
	},
	computed: {
		rows() {
			// 本组件只实现了'一行两列'的表单布局
			return Math.ceil(this.configs.fields.length / COLUMN_PER_ROW)
		}
	},
	mounted() {
		this.$nextTick(() => {
			/** 转换 configs.fields 的结构，把纯字符串转为对象 */
			this.configs.fields = this.configs.fields.map(item => {
				if (typeof item === 'string') {
					return { name: item }
				}
				return item
			})

			/** 动态设置dataForm字段 */
			this.configs.fields.forEach(item => {
				this.$set(this.dataForm, [item.name], '')
				if (item.api) {
					/** 自动请求并填充 */
					this.$http({
						url: this.$http.adornUrl(item.api),
						method: 'POST' // 也可以改成动态决定
					}).then(({ data: res }) => {
						if (res && res.code === 0) {
							this.dataForm[item.name] = res.data // <=== 此处需要对接口
						}
					})
				} // end if (item.api)

				if (item.required) {
					const requiredRule = {
						required: true,
						message: '请输入必填项',
						trigger: 'change'
					}
					/** 检查是否已经存在该字段的规则 */
					const exists = this.dataFormRules[item.name] || null
					/** 设置验证规则  */
					if (exists) {
						const unset = true
						for (const rule of exists) {
							if (rule.required) unset = false
						}
						if (unset) {
							exists.push(requiredRule)
						}
					} else {
						/** 不存在已有规则 */
						this.$set(this.dataFormRules, [item.name], [requiredRule])
					}
				} // end if (item.required)

				if (item.rules) {
					const exists = this.dataFormRules[item.name] || null
					if (exists) {
						// 浅拷贝过去
						exists.push(...item.rules)
					} else {
						this.$set(this.dataFormRules, [item.name], [...item.rules])
					}
				} // end if (item.rules)
			})

			/** 检查是否需要额外的组件 */
			this.configs.extraComponents &&
				this.configs.extraComponents.forEach(item => {
					this.$set(this.dataForm, [item.name], '')
				})

			/** 单独设置 id */
			this.$set(this.dataForm, 'id', null)

			// TODO：delete next lines
			console.log('dataform: ', this.dataForm)
			console.log('rules: ', this.dataFormRules)
		})
	},
	updated() {
		this.isUpdated = true // 此时如果点击保存就会 emit(refreshDataList)
	},
	// beforeDestroy() {
	// 缓存比较方案：
	// 在组件快要销毁时，比较localStorage和dataForm里的值
	// 如果有改变则 emit
	// 否则直接销毁
	// 清除localStorage里的缓存
	// if (cached && compareCache(this.dataForm, localStorage...) || !isEdit) {
	//   // 如果是编辑页面，并且已经更新了内容；或者是新增页面，就emit刷新列表
	//   clearCache()
	//   this.$emit('refreshDataList')
	// }
	// },
	methods: {
		getLabel(n, c) {
			const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
			if (opt) {
				// if opt is valid
				return opt.label ? opt.label : this.defaultNames[opt.name]
			}
		},
		getType(n, c) {
			const opt = this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]
			if (opt) {
				if (!opt.type || ['input', 'number' /** add more.. */].includes(opt.type)) {
					return 'input'
				} else if (['select' /** add more.. */].includes(opt.type)) {
					return 'select'
				}
				// add more...
			} else {
				return 'input'
			}
		},
		init() {
			this.visible = true
		},
		handleClick(btn) {
			this.$refs['dataForm'].validate(valid => {
				if (valid) {
					/** 提取url */
					const urls = {}
					this.configs.operations.map(item => {
						urls[item.name] = item.url
					})
					/** 操作 */
					switch (btn.name) {
						case 'save':
						case 'update':
							this.$http({
								url: this.$http.adornUrl(urls[btn.name]),
								method: btn.name === 'save' ? 'POST' : 'PUT',
								data: this.dataForm
							}).then(({ data: res }) => {
								if (res && res.code === 0) {
									this.$message({
										message: btn.name === 'save' ? '添加成功!' : '更新成功!',
										type: 'success',
										duration: 1500,
										onClose() {
											this.$emit('refreshDataList')
											this.visible = false
										}
									})
								}
							})
							return
						case 'reset':
							for (const key of Object.keys(this.dataForm)) {
								if (typeof this.dataForm[key] === 'string') {
									this.dataForm[key] = ''
								} else if (this.dataForm[key] instanceof Array) {
									this.dataForm[key].splice(0)
								} else {
									this.dataForm[key] = null
								}
							}
							console.log('after reset: ', JSON.stringify(this.dataForm))
							break
						// add more..
					}
				}
			})
		},
		handleClose() {
			if (this.isAdd || this.isUpdated) this.$emit('refreshDataList')
			this.visible = false
		}
	}
}
</script>

<style scoped>
.super-flexible-dialog >>> .el-select {
	width: 100%;
}
</style>
