"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const path_1 = require("path");
class FileApi {
    root;
    constructor(root) {
        this.root = root;
    }
    // public static instance: FileApi = new FileApi();
    parse(path) {
        return path_1.parse(path);
    }
    join(p1, p2) {
        return path_1.join(p1, p2);
    }
    resolve(...path) {
        if (path.length === 1) {
            return path_1.resolve(this.root, path[0]);
        }
        return path_1.resolve(...path);
    }
    relative(path1, path2) {
        return path_1.relative(path1, path2);
    }
    readString(path) {
        path = this.resolve(path);
        return new Promise((resolve, reject) => {
            fs.readFile(path, "utf8", (err, data) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve(data);
            });
        });
    }
    appendString(path, data) {
        path = this.resolve(path);
        return new Promise((resolve, reject) => {
            fs.appendFile(path, data, "utf8", (err) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve();
            });
        });
    }
    writeString(path, data) {
        path = this.resolve(path);
        if (typeof data !== "string") {
            data = JSON.stringify(data);
        }
        return new Promise((resolve, reject) => {
            fs.writeFile(path, data, "utf8", (err) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve();
            });
        });
    }
    exists(path) {
        path = this.resolve(path);
        return new Promise((resolve, reject) => {
            fs.access(path, fs.constants.F_OK, (error) => {
                resolve(!error);
            });
        });
    }
    async writeOnlyIfChanged(path, content) {
        path = this.resolve(path);
        if (await this.exists(path)) {
            const existing = await this.readString(path);
            if (existing === content) {
                return;
            }
            if (this.flat(existing) === this.flat(content)) {
                return;
            }
        }
        await this.writeString(path, content);
    }
    stat(file) {
        file = this.resolve(file);
        const filePath = file;
        return new Promise((resolve, reject) => {
            fs.stat(filePath, (error, result) => {
                if (error) {
                    reject(error);
                    return;
                }
                resolve(result);
            });
        });
    }
    statSync(file) {
        return fs.statSync(this.resolve(file));
    }
    async readDir(folder, filter = (file) => true, nest = false) {
        const filePath = typeof folder === "string" ? folder : path_1.format(folder);
        // read file names
        const result = await new Promise((resolve, reject) => {
            fs.readdir(this.resolve(filePath), (error, files) => {
                if (error) {
                    reject(error);
                    return;
                }
                resolve(files.map((s) => ({
                    ...path_1.parse(path_1.join(filePath, s))
                })));
            });
        });
        let all = [];
        await Promise.all(result.map(async (iterator) => {
            const fstat1 = await this.stat(path_1.format(iterator));
            const path = iterator;
            iterator.length = fstat1.size;
            iterator.isDirectory = fstat1.isDirectory();
            iterator.ext = path.ext;
            iterator.dir = path.dir;
            iterator.name = path.name;
            if (iterator.isDirectory && nest) {
                const children = await this.readDir(iterator, filter, true);
                all = all.concat(children);
            }
            else {
                if (filter(iterator)) {
                    all.push(iterator);
                }
            }
        }));
        return all;
    }
    flat(content) {
        return content
            .split("\n")
            .map((s) => s.trimRight())
            .join("\n");
    }
}
exports.default = FileApi;
// const fileApi = FileApi.instance;
// export default ;
//# sourceMappingURL=FileApi.js.map