var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
  function adopt(value) {
    return value instanceof P ? value : new P(function (resolve) {
      resolve(value);
    });
  }

  return new (P || (P = Promise))(function (resolve, reject) {
    function fulfilled(value) {
      try {
        step(generator.next(value));
      } catch (e) {
        reject(e);
      }
    }

    function rejected(value) {
      try {
        step(generator["throw"](value));
      } catch (e) {
        reject(e);
      }
    }

    function step(result) {
      result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
    }

    step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
};

var __asyncValues = this && this.__asyncValues || function (o) {
  if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
  var m = o[Symbol.asyncIterator],
      i;
  return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () {
    return this;
  }, i);

  function verb(n) {
    i[n] = o[n] && function (v) {
      return new Promise(function (resolve, reject) {
        v = o[n](v), settle(resolve, reject, v.done, v.value);
      });
    };
  }

  function settle(resolve, reject, d, v) {
    Promise.resolve(v).then(function (v) {
      resolve({
        value: v,
        done: d
      });
    }, reject);
  }
};

import fs from 'fs';
import path from 'path';
/**
 * Creates array in the format of Collection with data loaded from directory on filesystem.
 * The function loads all the data into memory!
 *
 * @param dir path to the directory
 */

export function makeCollectionFromFS(dir) {
  return __awaiter(this, void 0, void 0, function* () {
    if (typeof dir !== 'string') {
      throw new TypeError('dir has to be string!');
    }

    if (dir === '') {
      throw new TypeError('dir must not be empty string!');
    }

    return buildCollectionRelative(dir, '');
  });
}

function buildCollectionRelative(dir, relativePath) {
  var e_1, _a;

  return __awaiter(this, void 0, void 0, function* () {
    // Handles case when the dir is not existing or it is a file ==> throws an error
    const dirname = path.join(dir, relativePath);
    const entries = yield fs.promises.opendir(dirname);
    let collection = [];

    try {
      for (var entries_1 = __asyncValues(entries), entries_1_1; entries_1_1 = yield entries_1.next(), !entries_1_1.done;) {
        const entry = entries_1_1.value;
        const fullPath = path.join(dir, relativePath, entry.name);
        const entryPath = path.join(relativePath, entry.name);

        if (entry.isFile()) {
          collection.push({
            path: entryPath,
            data: new Uint8Array(yield fs.promises.readFile(fullPath))
          });
        } else if (entry.isDirectory()) {
          collection = [...(yield buildCollectionRelative(dir, entryPath)), ...collection];
        }
      }
    } catch (e_1_1) {
      e_1 = {
        error: e_1_1
      };
    } finally {
      try {
        if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) yield _a.call(entries_1);
      } finally {
        if (e_1) throw e_1.error;
      }
    }

    return collection;
  });
}
/**
 * Calculate folder size recursively
 *
 * @param dir the path to the folder to check
 * @returns size in bytes
 */


export function getFolderSize(dir) {
  var e_2, _a;

  return __awaiter(this, void 0, void 0, function* () {
    if (typeof dir !== 'string') {
      throw new TypeError('dir has to be string!');
    }

    if (dir === '') {
      throw new TypeError('dir must not be empty string!');
    }

    const entries = yield fs.promises.opendir(dir);
    let size = 0;

    try {
      for (var entries_2 = __asyncValues(entries), entries_2_1; entries_2_1 = yield entries_2.next(), !entries_2_1.done;) {
        const entry = entries_2_1.value;

        if (entry.isFile()) {
          const stats = yield fs.promises.stat(path.join(dir, entry.name));
          size += stats.size;
        } else if (entry.isDirectory()) {
          size += yield getFolderSize(path.join(dir, entry.name));
        }
      }
    } catch (e_2_1) {
      e_2 = {
        error: e_2_1
      };
    } finally {
      try {
        if (entries_2_1 && !entries_2_1.done && (_a = entries_2.return)) yield _a.call(entries_2);
      } finally {
        if (e_2) throw e_2.error;
      }
    }

    return size;
  });
}