class Storage {
  private namespace: string

  constructor(namespace?: string) {
    this.namespace = `CHONGDIAN_${namespace || 'DEFAULT'}`
  }

  set<T = any>(key: string, data: T, expire?: number): Promise<void> {
    const now = new Date().getTime()
    const _d = {
      data,
      expire: expire ? now + expire : 0
    }
    return new Promise((resolve, reject) => {
      uni.setStorage({
        key: `${this.namespace}_${key}`,
        data: JSON.stringify(_d),
        success() {
          resolve()
        },
        fail(err) {
          reject(err)
        }
      })
    })
  }

  get<T = any>(key: string, defaultValue?: T): Promise<T | undefined> {
    return new Promise(resolve => {
      const _key = `${this.namespace}_${key}`
      uni.getStorage({
        key: _key,
        success(res) {
          if (res && res.data) {
            try {
              const data = JSON.parse(res.data)
              if (!data.expire) {
                resolve(data.data)
                return
              }
              const now = new Date().getTime()
              if (now <= data.expire) {
                resolve(data.data)
                return
              }
            } catch (error) {
              // eslint-disable-next-line no-console
              console.log(error)
            }
          }
          uni.removeStorage({
            key: _key
          })
          resolve(defaultValue ? defaultValue : undefined)
        },
        fail(err) {
          resolve(defaultValue ? defaultValue : undefined)
          return err
        }
      })
    })
  }

  clear(key?: string): Promise<void> {
    if (key) {
      const _key = `${this.namespace}_${key}`
      return this.rm(_key)
    }
    return new Promise((resolve, reject) => {
      uni.getStorageInfo({
        success: res => {
          if (res.keys && res.keys.length) {
            const reg = new RegExp(`^${this.namespace.replace(/\^/gi, '\\^')}.+`)
            const ps: Promise<void>[] = []
            res.keys.forEach(key => {
              if (reg.test(key)) {
                ps.push(this.rm(key))
              }
            })
            Promise.all(ps)
              .then(() => {
                resolve()
                return true
              })
              .catch(reject)
            return
          }
          resolve()
        },
        fail: err => {
          reject(err)
        }
      })
    })
  }

  private rm(key: string): Promise<void> {
    return new Promise((resolve, reject) => {
      uni.removeStorage({
        key,
        success() {
          resolve()
        },
        fail(err) {
          reject(err)
        }
      })
    })
  }
}

export default Storage
