import Vue from 'vue'
import {
	mergeRecursive
} from "@/utils/ruoyi";
import DictMeta from './DictMeta'
import DictData from './DictData'

const DEFAULT_DICT_OPTIONS = {
	types: [],
}

/**
 * @classdesc 字典
 * @property {Object} label 标签对象，内部属性名为字典类型名称
 * @property {Object} dict 字段数组，内部属性名为字典类型名称
 * @property {Array.<DictMeta>} _dictMetas 字典元数据数组
 */
export default class Dict {
	constructor() {
		this.owner = null
		this.label = {}
		this.type = {}
	}

	init(options) {
		if (options instanceof Array) {
			options = {
				types: options
			}
		}
		const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
		if (opts.types === undefined) {
			throw new Error('need dict types')
		}
		const ps = []
		this._dictMetas = opts.types.map(t => DictMeta.parse(t))
		this._dictMetas.forEach(dictMeta => {
			const type = dictMeta.type
			Vue.set(this.label, type, {})
			Vue.set(this.type, type, [])
			if (dictMeta.lazy) {
				return
			}
			ps.push(loadDict(this, dictMeta))
		})
		return Promise.all(ps)
	}

	/**
	 * 重新加载字典
	 * @param {String} type 字典类型
	 */
	reloadDict(type) {
		const dictMeta = this._dictMetas.find(e => e.type === type)
		if (dictMeta === undefined) {
			return Promise.reject(`the dict meta of ${type} was not found`)
		}
		return loadDict(this, dictMeta)
	}
}

/**
 * 加载字典
 * @param {Dict} dict 字典
 * @param {DictMeta} dictMeta 字典元数据
 * @returns {Promise}
 */
function loadDict(dict, dictMeta) {
	return dictMeta.request(dictMeta)
		.then(response => {
			const type = dictMeta.type
			let dicts = dictMeta.responseConverter(response, dictMeta)
			// #ifdef H5
			if (!(dicts instanceof Array)) {
				console.error('the return of responseConverter must be Array.<DictData>')
				dicts = []
			} else
				// #endif
				if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
					console.error('the type of elements in dicts must be DictData')
					dicts = []
				}
			dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
			dicts.forEach(d => {
				Vue.set(dict.label[type], d.value, d.label)
			})
			return dicts
		})
}