<template>
	<el-dialog class="super-flexible-dialog" :title="isDetail ? title.detail : !dataForm.id ? title.add : title.edit" :visible.sync="visible" @close="handleClose">
		<el-form :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 || configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]"
						: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]"
						/>
						<el-radio v-if="getType(n, c) === 'radio'"></el-radio>
						<el-checkbox v-if="getType(n, c) === 'check'"></el-checkbox>
						<el-select v-if="getType(n, c) === 'select'" :placeholder="configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].placeholder || ''"></el-select>
						<el-switch v-if="getType(n, c) === 'switch'"></el-switch>
						<el-cascader v-if="getType(n, c) === 'tree'"></el-cascader>
						<el-time-select v-if="getType(n, c) === 'time'"></el-time-select>
						<el-date-picker v-if="getType(n, c) === 'date'"></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">
			<el-button v-for="(operate, index) in configs.operations" :key="`operate-${index}`" :type="btnType[operate.name]" @click="handleClick(operate)">
				<!-- {{ operate.name | btnNameFilter }} -->
				{{ btnName[operate.name] }}
			</el-button>
		</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], 操作名和对应的接口地址
			 */
			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)
		}
		// computedModel: {
		// 	get(n, c) {
		// 		return this.configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name
		// 			? dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)].name]
		// 			: dataForm[configs.fields[(n - 1) * COLUMN_PER_ROW + (c - 1)]]
		// 	},
		// 	set() {}
		// }
	},
	mounted() {
		this.$nextTick(() => {
			/** 动态设置dataForm字段 */
			this.configs.fields.forEach(item => {
				if (typeof item === 'string') {
					this.$set(this.dataForm, [item], '')
				} else if (typeof item === 'object') {
					this.$set(this.dataForm, [item.name], '')
					if (item.api) {
						/** 自动请求并填充 */
						this.$http({
							url: this.$http.adornUrl(item.api),
							methods: 'get'
						}).then(({ data: res }) => {
							if (data & (data.code === 0)) {
								this.dataFrom[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 typeof opt === 'string' ? this.defaultNames[opt] : 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) {
			switch (btn.name) {
				case 'save':
					break
				case 'update':
					break
				case 'reset':
					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>
