import Hash from './Hash.js';

/**
 * Gets the data for `map`.
 * 获取“map”的数据。
 * @private
 * @param {Object} map 要查询的映射。
 * @param {string} key 参考关键。
 * @returns {*} 返回地图数据。
 */
function getMapData({ __data__ }, key) {
	const data = __data__;
	return isKeyable(key) ? data[typeof key === 'string' ? 'string' : 'hash'] : data.map;
}

/**
 * Checks if `value` is suitable for use as unique object key.
 * 检查' value '是否适合用作唯一的对象键。
 * @private
 * @param {*} value 要检查的值。
 * @returns {boolean} 如果' value '合适，则返回' true '，否则返回' false '。
 */
function isKeyable(value) {
	const type = typeof value;
	return type === 'string' || type === 'number' || type === 'symbol' || type === 'boolean'
		? value !== '__proto__'
		: value === null;
}

class MapCache {
	/**
	 * Creates a map cache object to store key-value pairs.
	 * 创建一个映射缓存对象来存储键值对
	 * @private
	 * @constructor
	 * @param {Array} [entries] 要缓存的键值对。
	 */
	constructor(entries) {
		let index = -1;
		const length = entries == null ? 0 : entries.length;

		this.clear();
		while (++index < length) {
			const entry = entries[index];
			this.set(entry[0], entry[1]);
		}
	}

	/**
	 * Removes all key-value entries from the map.
	 * 从映射中删除所有键值项。
	 * @memberOf MapCache
	 */
	clear() {
		this.size = 0;
		this.__data__ = {
			hash: new Hash(),
			map: new Map(),
			string: new Hash(),
		};
	}

	/**
	 * Removes `key` and its value from the map.
	 * 从映射中删除' key '及其值。
	 * @memberOf MapCache
	 * @param {string} key 要删除的值的键。
	 * @returns {boolean} 如果条目被删除，则返回“true”，否则返回“false”。
	 */
	delete(key) {
		const result = getMapData(this, key)['delete'](key);
		this.size -= result ? 1 : 0;
		return result;
	}

	/**
	 * Gets the map value for `key`.
	 * 获取' key '的映射值。
	 * @memberOf MapCache
	 * @param {string} key 要获取的值的键。
	 * @returns {*} 返回条目值。
	 */
	get(key) {
		return getMapData(this, key).get(key);
	}

	/**
	 * Checks if a map value for `key` exists.
	 * 检查' key '的map值是否存在。
	 * @memberOf MapCache
	 * @param {string} key 要检查的key。
	 * @returns {boolean} 如果' key '的条目存在，则返回' true '，否则返回' false '。
	 */
	has(key) {
		return getMapData(this, key).has(key);
	}

	/**
	 * Sets the map `key` to `value`.
	 * 将映射“键”设置为“值”。
	 * @memberOf MapCache
	 * @param {string} key 要设置的值的键。
	 * @param {*} value 要设置的值。
	 * @returns {Object} 返回映射缓存实例。
	 */
	set(key, value) {
		const data = getMapData(this, key);
		const size = data.size;

		data.set(key, value);
		this.size += data.size == size ? 0 : 1;
		return this;
	}
}

export default MapCache;
