"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTmpDirPath = exports.rmDir = exports.recursiveReadDir = exports.prepareDir = exports.createDir = exports.readDir = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const os_1 = require("os");
const mkdirp_1 = __importDefault(require("mkdirp"));
const recursive_readdir_1 = __importDefault(require("recursive-readdir"));
const rimraf_1 = __importDefault(require("rimraf"));
const minimatch_1 = require("minimatch");
const crypto_1 = require("@f2/crypto");
const info_1 = require("./info");
/**
 * Lecture des fichiers et dossiers d'un répertoire
 *
 * Si absolute=true, les chemins sont renvoyés de manière absolue
 */
function readDir(path, absoluteOrOptions = false) {
    return new Promise((resolve, reject) => {
        let absolute = false;
        let dirent = false;
        if (typeof absoluteOrOptions === 'boolean') {
            absolute = absoluteOrOptions;
        }
        else {
            absolute = absoluteOrOptions.absolute || absolute;
            dirent = absoluteOrOptions.dirent || dirent;
        }
        if (dirent) {
            fs_1.default.readdir(path, {
                withFileTypes: true
            }, (err, files) => {
                if (err) {
                    reject(err);
                    return;
                }
                if (absolute) {
                    files.forEach((f) => f.name = (0, path_1.join)(path, f.name));
                }
                resolve(files);
            });
            return;
        }
        fs_1.default.readdir(path, (err, files) => {
            if (err) {
                reject(err);
                return;
            }
            if (absolute) {
                files = files.map((file) => (0, path_1.join)(path, file));
            }
            resolve(files);
        });
    });
}
exports.readDir = readDir;
/**
 * Création d'un répertoire
 *
 * @param {String} path
 *
 * @returns {promise}
 */
async function createDir(path) {
    await (0, mkdirp_1.default)(path);
}
exports.createDir = createDir;
/**
 * Préparation d'un répertoire
 *
 * @param {String} path
 *
 * @returns {promise}
 */
async function prepareDir(path) {
    const access = await (0, info_1.accessPath)(path);
    if (access) {
        return;
    }
    await createDir(path);
}
exports.prepareDir = prepareDir;
/**
 * Lecture récursive d'un dossier
 */
async function recursiveReadDir(path, options) {
    const realPath_ = await (0, info_1.realPath)(path);
    return new Promise((resolve, reject) => {
        if (!options) {
            options = {};
        }
        const cb = async (error, paths) => {
            if (error) {
                reject(error);
                return;
            }
            if (options.absolute) {
                resolve(paths);
            }
            else {
                const basepath = realPath_ + '/';
                resolve(paths.map((_path) => {
                    return _path.replace(basepath, '');
                }));
            }
        };
        const filters = [];
        const exclude = options.exclude;
        if (exclude) {
            if (exclude instanceof Array) {
                filters.push(...exclude);
            }
            else {
                filters.push(exclude);
            }
        }
        const include = options.include;
        if (include) {
            const includes = include instanceof Array ? include : [include];
            const includePatterns = includes.filter((include) => {
                if (typeof include === 'function') {
                    filters.push((f, s) => {
                        return !include(f, s);
                    });
                }
                return typeof include === 'string';
            });
            if (includePatterns.length) {
                filters.push((i, s) => {
                    if (s.isDirectory()) {
                        return false;
                    }
                    return includePatterns.every((pattern) => {
                        return !(0, minimatch_1.minimatch)(i, pattern, {
                            dot: true
                        });
                    });
                });
            }
        }
        if (filters.length) {
            (0, recursive_readdir_1.default)(realPath_, filters, cb);
        }
        else {
            (0, recursive_readdir_1.default)(realPath_, cb);
        }
    });
}
exports.recursiveReadDir = recursiveReadDir;
function rmDir(path) {
    return (0, rimraf_1.default)(path);
}
exports.rmDir = rmDir;
function getTmpDirPath(suffix) {
    const maxAttempts = 10;
    let attemptCount = 0;
    return new Promise((resolve, reject) => {
        const osTmpDirPath = (0, os_1.tmpdir)();
        const tryGenerate = async () => {
            attemptCount++;
            try {
                const dirpath = await (0, crypto_1.generate)(16);
                const tmpPath = (0, path_1.join)(osTmpDirPath, dirpath + (suffix ? '-' + suffix : ''));
                const exists = await (0, info_1.accessPath)(tmpPath);
                if (exists) {
                    throw new Error(`Tmp dir ${tmpPath} existe déjà`);
                }
                await prepareDir(tmpPath);
                resolve(tmpPath);
            }
            catch (err) {
                if (maxAttempts > attemptCount) {
                    setImmediate(tryGenerate);
                    return;
                }
                reject(new Error('Impossible de générer un chemin temporaire valide'));
            }
        };
        tryGenerate();
    });
}
exports.getTmpDirPath = getTmpDirPath;
