/**
 * localStorage utils
 */

export const lastUpdatedSuffix = '__lastUpdated';

export default {
  set(key: string, value: unknown) {
    try {
      localStorage.setItem(key, JSON.stringify(value));
      return true;
    } catch {
      return false;
    }
  },

  get<Value = unknown>(key: string): Value | null {
    const value = localStorage.getItem(key);
    if (value === null) return null;
    try {
      return JSON.parse(value);
    } catch {
      return value as unknown as Value;
    }
  },

  remove(key: string) {
    try {
      localStorage.removeItem(key);
      return true;
    } catch {
      return false;
    }
  },

  // Watch changes to a specified key - returns value on change
  watch<Value = unknown>(key: string, callback: (value: Value | null) => void) {
    const handler = (event: StorageEvent) => {
      if (event.key === key) callback(this.get<Value>(key));
    };
    window.addEventListener('storage', handler);
    return () => window.removeEventListener('storage', handler);
  },

  // set() with an additional key containing the current time + expiration time
  setWithExpireTime(key: string, value: unknown, maxAge: number) {
    const lastUpdatedKey = key + lastUpdatedSuffix;
    const lastUpdatedTime = Date.now() + maxAge;

    return this.set(key, value) && this.set(lastUpdatedKey, lastUpdatedTime);
  },

  // Whether the value of a key set with setWithExpireTime() has expired
  hasExpired(key: string) {
    const lastUpdatedKey = key + lastUpdatedSuffix;
    const lastUpdatedTime = this.get<number>(lastUpdatedKey);

    return lastUpdatedTime === null || Date.now() > lastUpdatedTime;
  },
};