import { createLocalStorage } from '@/utils/cache'
import type { RouteLocationNormalized } from 'vue-router'

import {
  TOKEN_KEY,
  USER_INFO_KEY,
  PERMISSIONS_KEY,
  LOCK_INFO_KEY,
  ROUTER_KEY,
  APP_LOCAL_CACHE_KEY,
  DEFAULT_CACHE_TIME,
  UNDONE_COUNT,
  UNDONE_COUNT_INVAL
} from '@/enums/cacheEnum'
import { toRaw } from 'vue'
import { pick, omit } from 'lodash'
import { Memory } from './memory'

declare type Nullable<T> = T | null

export interface LockInfo {
  // Password required
  pwd?: string | undefined
  // Is it locked?
  isLock?: boolean
}

interface BasicStore {
  [UNDONE_COUNT_INVAL]: number
  [UNDONE_COUNT]: number
  [TOKEN_KEY]: string | number | null | undefined
  [USER_INFO_KEY]: { username: string; userId?: string }
  [PERMISSIONS_KEY]: string[]
  [LOCK_INFO_KEY]: LockInfo
  [ROUTER_KEY]: RouteLocationNormalized
}

type LocalStore = BasicStore

export type BasicKeys = keyof BasicStore
// Lock screen information

type LocalKeys = keyof LocalStore

const ls = createLocalStorage()

const localMemory = new Memory(DEFAULT_CACHE_TIME)

function initPersistentMemory() {
  const localCache = ls.get(APP_LOCAL_CACHE_KEY)
  localCache && localMemory.resetCache(localCache)
}

export class Persistent {
  static getLocal<T>(key: LocalKeys) {
    return localMemory.get(key)?.value as Nullable<T>
  }

  static setLocal(
    key: LocalKeys,
    value: LocalStore[LocalKeys],
    immediate = false
  ): void {
    localMemory.set(key, toRaw(value))
    immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache)
  }

  static removeLocal(key: LocalKeys, immediate = false): void {
    localMemory.remove(key)
    immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache)
  }

  static clearLocal(immediate = false): void {
    localMemory.clear()
    immediate && ls.clear()
  }

  static clearAll(immediate = false) {
    localMemory.clear()
    if (immediate) {
      ls.clear()
    }
  }
}

// function test() {
//   // TOKEN_KEY 在登录或注销时已经写入到storage了，此处为了解决同时打开多个窗口时token不同步的问题
//   // LOCK_INFO_KEY 在锁屏和解锁时写入，此处也不应修改
//   ls.set(APP_LOCAL_CACHE_KEY, {
//     ...omit(localMemory.getCache, LOCK_INFO_KEY),
//     ...pick(ls.get(APP_LOCAL_CACHE_KEY), [
//       TOKEN_KEY,
//       USER_INFO_KEY,
//       LOCK_INFO_KEY
//     ])
//   })
// }

window.addEventListener('beforeunload', function (event) {
  // TOKEN_KEY 在登录或注销时已经写入到storage了，此处为了解决同时打开多个窗口时token不同步的问题
  // LOCK_INFO_KEY 在锁屏和解锁时写入，此处也不应修改
  ls.set(APP_LOCAL_CACHE_KEY, {
    ...omit(localMemory.getCache, LOCK_INFO_KEY),
    ...pick(ls.get(APP_LOCAL_CACHE_KEY), [
      TOKEN_KEY,
      UNDONE_COUNT,
      USER_INFO_KEY,
      LOCK_INFO_KEY
    ])
  })
})

function storageChange(e: any) {
  const { key, newValue, oldValue } = e
  if (!key) {
    Persistent.clearAll()
    return
  }

  if (!!newValue && !!oldValue) {
    if (APP_LOCAL_CACHE_KEY === key) {
      Persistent.clearLocal()
    }
  }
}

window.addEventListener('storage', storageChange)

initPersistentMemory()
