export class DengiCaching {
  /**
   * @type {{name: string, value: any, expires: Date}[]}
   */
  vals = [];
  constructor() {}
  tick() {
    this.vals.map((element, index) => {
      if (element.expires < new Date()) {
        if (index > -1) {
          this.vals = this.vals.splice(index, 1);
        }
      }
    });
  }
  /**
   * @param {string} name
   * @param {()=>any} ifNotFound - function, would be called if value not found, returned value vould be stored
   */
  withCache(name, ifNotFound) {
    this.tick();
    let a = this.get(name);
    if (a === undefined) {
      let c = ifNotFound();
      this.cache(name, c);
      return c;
    } else {
      return a;
    }
  }
  /**
   * @param {string} name
   * @param {()=>any} ifNotFound - function, would be called if value not found, returned value vould be stored
   */
  async withCacheAsync(name, ifNotFound) {
    this.tick();
    let a = this.get(name);
    if (a === undefined) {
      let c = await ifNotFound();
      this.cache(name, c);
      return c;
    } else {
      return a;
    }
  }
  /**
   *
   * @param  {...string} names
   */
  delete(...names) {
    names.forEach((name) => {
      var index = this.vals.findIndex((a) => a.name == name);
      if (index > -1) {
        this.vals = this.vals.splice(index, 1);
      }
      this.tick();
    });
  }
  fullClear() {
    this.vals = [];
  }
  /**
   * @param {string} name
   */
  wasCached(name) {
    this.tick();
    return this.vals.find((a) => a.name == name) !== undefined;
  }
  /**
   * @param {string} name
   */
  get(name) {
    this.tick();
    const item = this.vals.find((a) => a.name === name);
    return item ? item.value : undefined;
  }
  /**
   * @param {string} name
   * @param {any} val
   */
  cache(name, val) {
    this.tick();
    this.vals.push({
      name: name,
      value: val,
      expires: new Date(Date.now() + 60 * 60 * 1000),
    });
  }
}
