import * as plugins from './levelcache.plugins.js';
import * as paths from './levelcache.paths.js';
import { AbstractCache } from './levelcache.abstract.classes.cache.js';
import { type ILevelCacheConstructorOptions, LevelCache } from './levelcache.classes.levelcache.js';
import { CacheEntry } from './levelcache.classes.cacheentry.js';

/**
 *
 */
export class CacheDiskManager extends AbstractCache {
  private levelCacheRef: LevelCache;
  private readyDeferred = plugins.smartpromise.defer<void>();

  public ready = this.readyDeferred.promise;
  public status: 'active' | 'inactive';
  public fsPath: string;
  public maxCacheSizeInMb: number;

  constructor(levelCacheRefArg: LevelCache) {
    super();
    this.levelCacheRef = levelCacheRefArg;
    this.init();
  }

  public async init() {
    if (this.levelCacheRef.options.diskStoragePath) {
      this.fsPath = plugins.path.join(
        this.levelCacheRef.options.diskStoragePath,
        this.levelCacheRef.options.cacheId
      );
    } else {
      this.fsPath = plugins.path.join(paths.nogitDir, this.levelCacheRef.options.cacheId);
    }
    if (this.status === 'active') {
      plugins.smartfile.fs.ensureDirSync(this.fsPath);
    }
    this.readyDeferred.resolve();
  }

  public async retrieveCacheEntryByKey(keyArg: string): Promise<CacheEntry> {
    const fileString = await plugins.smartfile.fs.toStringSync(
      plugins.path.join(this.fsPath, encodeURIComponent(keyArg))
    );
    return CacheEntry.fromStorageJsonString(fileString);
  }

  public async storeCacheEntryByKey(keyArg: string, cacheEntryArg: CacheEntry) {
    await plugins.smartfile.memory.toFs(
      cacheEntryArg.foldToJson(),
      plugins.path.join(this.fsPath, encodeURIComponent(keyArg))
    );
  }

  public async checkKeyPresence(keyArg: string): Promise<boolean> {
    return plugins.smartfile.fs.isFile(plugins.path.join(this.fsPath, encodeURIComponent(keyArg)));
  }

  public async deleteCacheEntryByKey(keyArg: string) {
    await plugins.smartfile.fs.remove(plugins.path.join(this.fsPath, encodeURIComponent(keyArg)));
  }

  public async cleanOutdated() {}

  public async cleanAll() {
    if (this.status === 'active') {
      if (plugins.smartfile.fs.isDirectory(this.fsPath)) {
        await plugins.smartfile.fs.ensureEmptyDir(this.fsPath);
      }
    }
  }
}
