/**
 * 状态管理
 */

const data = new Map<string, any | null>()
const store = reactive(data);

export class Store {
	private STORE_KEY: string = 'UXFRAME_STORE_KEY'
	private keys: Map<string, number> = new Map<string, number>()
	
	constructor() {
		let data = uni.getStorageSync(this.STORE_KEY)
		if(data != null && data != '') {
			let keys = data as UTSJSONObject
			for (let k in keys) {
				this.keys.set(k, keys[k] as number)
			}
			
			this.keys.forEach((_: number, k: string) => {
				let _key = this.getKey(k)
				uni.getStorage({
					key: _key,
					success: (res) => {
						store.set(_key, res.data)
					},
					fail: (err) => {
						console.log(err);
						this.keys.delete(k)
						this.saveKeys()
					}
				})
			})
		}
		
		// 3s周期清理过期keys
		setInterval(() => {
			this.keys.forEach((_:number, k:string) => {
				this.removeExpires(k)
			})
		}, 3000)
	}
	
	/**
	 * 获取缓存数据
	 * @param key 键
	 * @returns {any}
	 */
	get(key : string) : any | null {
		this.removeExpires(key)
		return store.get(this.getKey(key))
	}
	
	/**
	 * 内存缓存数据，不会持久化
	 * @param key 键
	 * @param value 值
	 */
	set(key : string, value : any) {
		store.set(this.getKey(key), value)
		this.setKey(key, 0)
	}
	
	/**
	 * 持久化缓存数据，可设置过期时间
	 * 持久化存储只支持原生类型、及能够通过 JSON.stringify 序列化的对象
	 * @param key 键
	 * @param value 值
	 * @param expires <= 0 永不过期; > 0 过期时间 单位ms
	 */
	setExpires(key : string, value : any, expires: number): void {
		let _key = this.getKey(key)
		
		uni.setStorage({
			key: _key,
			data: value,
			success: () => {
				store.set(_key, value)
				this.setKey(key, expires)
			},
			fail: (err) => {
				console.error('[UxFrame] setExpires error', key, err);
			}
		})
	}
	
	/**
	 * 删除数据
	 * @param key 键
	 */
	delete(key : string) {
		let _key = this.getKey(key)
		store.delete(_key)
		this.keys.delete(key)
		uni.removeStorageSync(_key)
		this.saveKeys()
	}
	
	/**
	 * 清空数据
	 */
	clear() {
		store.clear()
		this.keys.forEach((_: number, k: string) => {
			uni.removeStorageSync(this.getKey(k))
		})
		this.keys.clear()
		this.saveKeys()
	}
	
	/**
	 * Key
	 */
	private getKey(key: string): string {
		return this.STORE_KEY + key
	}
	
	/**
	 * 获取keys
	 */
	getKeys(): Map<string, number> {
		return this.keys
	}
	
	/**
	 * 设置key
	 */
	private setKey(key: string, expires: number) {
		this.keys.set(key, expires == 0 ? 0 : (new Date().getTime() + expires))
		this.saveKeys()
	}
	
	/**
	 * 持久化keys
	 */
	private saveKeys() {
		let keys = {} as UTSJSONObject
		this.keys.forEach((v: number, k: string) => {
			keys[k] = v
		})
		
		uni.setStorage({
			key: this.STORE_KEY,
			data: keys
		})
	}
	
	/**
	 * 移除过期key
	 * @param key 键
	 */
	private removeExpires(key: string) {
		if(this.keys.has(key)) {
			let expires = this.keys.get(key) ?? 0
			if(expires > 0) {
				if(new Date().getTime() >= expires) {
					this.delete(key)
				}
			}
		}
	}
}