export class DataProvider {
	constructor() {
		this.data = {};
	}

	set(name, data) {
		this.data[name] = data;
	}

	get(name) {
		return this.data[name];
	}

	setRaw(name, data) {
		this.set("raw." + name, data);
	}

	getRaw(name) {
		return this.get("raw." + name);
	}

	/**
	 * Удалить конкретный ключ из кеша.
	 * Вызывать после мутаций — например, после переименования устройства.
	 */
	invalidate(key) {
		delete this.data[key];
	}

	/**
	 * Удалить все ключи, начинающиеся с prefix.
	 * Например: invalidatePrefix("raw.devices") очищает весь кеш устройств.
	 */
	invalidatePrefix(prefix) {
		for (const key of Object.keys(this.data)) {
			if (key.startsWith(prefix)) {
				delete this.data[key];
			}
		}
	}

	/**
	 * Вернуть данные из кеша; если их нет — вызвать fetchFn, закешировать и вернуть.
	 *
	 * @param {string}   key      Ключ в хранилище, например "raw.devices.12"
	 * @param {function} fetchFn  (cb) => void  — должна вызвать cb(err, data)
	 * @param {function} cb       (err, data) => void
	 *
	 * Пример:
	 *   DataProvider.getOrFetch(
	 *     `raw.devices.${id}`,
	 *     (cb) => sh_api.devices.get(id, (err, resp) => cb(err, resp?.data?.device)),
	 *     (err, device) => { ... }
	 *   );
	 */
	getOrFetch(key, fetchFn, cb) {
		const cached = this.data[key];
		if (typeof cached !== "undefined") {
			return cb(null, cached);
		}

		fetchFn((err, data) => {
			if (!err && typeof data !== "undefined") {
				this.data[key] = data;
			}
			cb(err, data);
		});
	}

	/**
	 * Вернуть массив всех закешированных значений, чьи ключи начинаются с prefix.
	 * Например: getCollection("raw.devices") → [device, device, ...]
	 */
	getCollection(prefix) {
		const result = [];
		for (const [key, value] of Object.entries(this.data)) {
			if (key.startsWith(prefix)) {
				result.push(value);
			}
		}
		return result;
	}
}
