import fs from 'fs';
import util from 'util';
import path from 'path';
import Bobolink from 'bobolink';
import { logger } from '../utils/logger';
import makirp from 'mkdirp';

export default new class {
  public bobolink = new Bobolink({
    concurrency: 5,
    timeout: 0,
    handler: (cb: any) => cb(),
  });

  public constants = fs.constants;

  public access = util.promisify(fs.access);

  public mkdir = makirp.sync;

  public writeFile = util.promisify(fs.writeFile);

  public readFile = util.promisify(fs.readFile);

  public symlink = util.promisify(fs.symlink);

  public unlink = util.promisify(fs.unlink);

  public rmdir = util.promisify(fs.rmdir);

  public lstat = util.promisify(fs.lstat);

  public statSync = fs.statSync;

  public readdir = util.promisify(fs.readdir);

  public rename = util.promisify(fs.rename);

  public async link(source: string, target: string) {
    try {
      const stats = await this.lstat(target);
      if (stats.isFile() || stats.isSymbolicLink()) {
        await this.unlink(target);
      } else if (stats.isDirectory()) {
        await this.deleteDir(target);
      }
    } catch (e) {
      logger.debug(`路径软链：${e}`);
    }
    return this.symlink(source, target);
  }

  public async deleteDir(dirPath: string) {
    const files = await this.readdir(dirPath);
    const awaitPs = [];
    for (let file of files) {
      file = path.join(dirPath, file);
      const stats = await this.lstat(file);
      if (stats.isDirectory()) {
        await this.deleteDir(file);
      }
      const res = this.bobolink.push(() => this.unlink(file));
      awaitPs.push(res);
    }
    await Promise.all(awaitPs);
    return this.rmdir(dirPath);
  }
};
