import * as React from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { LocalStorage } from '@assets/js-shop/LocalStorage';

const CACHE_KEY_PERSISTED_STORAGE = 'js-shop-data-';

interface IStorageCacheItem<K> {
   id: K;
   item: any;
   exp: number;
}

export interface IPersistedMap<K> {
   get: (id: K) => any | null;
   set: (id: K, item: any, ttlSec: number) => void;
   setAndSave: (id: K, item: any, ttlSec: number) => void;
   has: (id: K) => boolean;
   persist: () => void;
}

// js Map, který se ukládá v localStorage, každá položka v mapě má vlastní TTL
export function usePersistedMap<K>(storageKey: string): IPersistedMap<K> {
   let storage: React.MutableRefObject<Map<K, IStorageCacheItem<K>>> = useRef(new Map());

   useEffect(() => {
      loadCache();
   }, []);

   const loadCache = useCallback(() => {
      const localStorage: IStorageCacheItem<K>[] | null = LocalStorage.get(getPersistedMapStorageKey(storageKey));
      (localStorage || []).forEach((item) => {
         if (item.exp > new Date().getTime()) {
            storage.current.set(item.id, item);
         }
      });
   }, []);

   const persist = useCallback(() => {
      const localStorage = Array.from(storage.current.values());
      LocalStorage.set(getPersistedMapStorageKey(storageKey), localStorage);
   }, []);

   const set = useCallback((id: K, item: any, ttlSec: number) => {
      storage.current.set(id, { id, item, exp: getExpMillis(ttlSec) });
   }, []);

   const setAndSave = useCallback((id: K, item: any, ttlSec: number) => {
      set(id, item, ttlSec);
      persist();
   }, []);

   const get = useCallback((id: K) => {
      if (storage.current.has(id)) {
         const item = storage.current.get(id);
         if (item.exp > getExpMillis()) {
            return item.item;
         }
      }
      return null;
   }, []);

   const has = useCallback((id: K) => {
      return storage.current.has(id) && storage.current.get(id).exp > getExpMillis();
   }, []);

   return { get, set, setAndSave, has, persist };
}

export const clearPersistedMapStorage = (storageKey: string) => LocalStorage.remove(getPersistedMapStorageKey(storageKey));
const getPersistedMapStorageKey = (storageKey: string) => CACHE_KEY_PERSISTED_STORAGE + storageKey;
const getExpMillis = (plusSec = 0) => {
   return new Date().getTime() + plusSec * 1000;
};
