"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var fs_extra_1 = require("fs-extra");
var walk = require("klaw");
var path = require("path");
var api_1 = require("./api");
var utils_1 = require("./utils");
var memory_fs_1 = require("./memory-fs");
// TODO extract chokidar watch mechanism to configuration
var LocalFileSystemCrudOnly = /** @class */ (function () {
    function LocalFileSystemCrudOnly(baseUrl, ignore) {
        this.baseUrl = baseUrl;
        this.events = utils_1.makeEventsEmitter();
        this.isIgnored = function () { return false; };
        if (ignore) {
            this.isIgnored = utils_1.getIsIgnored(ignore);
        }
    }
    LocalFileSystemCrudOnly.prototype.saveFile = function (relPath, newContent) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var pathArr, name, fullPath;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (this.isIgnored(relPath)) {
                            throw new Error("Unable to save ignored path: '" + relPath + "'");
                        }
                        pathArr = utils_1.getPathNodes(relPath);
                        name = pathArr.pop() || '';
                        fullPath = path.join.apply(path, [this.baseUrl].concat(pathArr));
                        return [4 /*yield*/, fs_extra_1.ensureDir(fullPath)];
                    case 1:
                        _a.sent();
                        return [4 /*yield*/, fs_extra_1.writeFile(path.join(fullPath, name), newContent)];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    LocalFileSystemCrudOnly.prototype.deleteFile = function (relPath) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var fullPath, stats, e_1;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!relPath) {
                            throw new Error("Can't delete root directory");
                        }
                        if (this.isIgnored(relPath)) {
                            return [2 /*return*/];
                        }
                        fullPath = path.join.apply(path, [this.baseUrl].concat(utils_1.getPathNodes(relPath)));
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 4, , 5]);
                        return [4 /*yield*/, fs_extra_1.access(fullPath)];
                    case 2:
                        _a.sent();
                        return [4 /*yield*/, fs_extra_1.stat(fullPath)];
                    case 3:
                        stats = _a.sent();
                        return [3 /*break*/, 5];
                    case 4:
                        e_1 = _a.sent();
                        return [3 /*break*/, 5];
                    case 5:
                        if (stats) {
                            if (stats.isFile()) {
                                return [2 /*return*/, fs_extra_1.remove(fullPath)];
                            }
                            else {
                                throw new Error("not a file: " + relPath);
                            }
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    LocalFileSystemCrudOnly.prototype.deleteDirectory = function (relPath, recursive) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var pathArr, fullPath, stats, e_2;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        pathArr = utils_1.getPathNodes(relPath);
                        if (pathArr.length === 0) {
                            throw new Error("Can't delete root directory");
                        }
                        if (this.isIgnored(relPath)) {
                            return [2 /*return*/];
                        }
                        fullPath = path.join.apply(path, [this.baseUrl].concat(pathArr));
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 4, , 5]);
                        return [4 /*yield*/, fs_extra_1.access(fullPath)];
                    case 2:
                        _a.sent();
                        return [4 /*yield*/, fs_extra_1.stat(fullPath)];
                    case 3:
                        stats = _a.sent();
                        return [3 /*break*/, 5];
                    case 4:
                        e_2 = _a.sent();
                        return [3 /*break*/, 5];
                    case 5:
                        if (stats) {
                            if (stats.isDirectory()) {
                                return [2 /*return*/, recursive ? fs_extra_1.remove(fullPath) : fs_extra_1.rmdir(fullPath)];
                            }
                            else {
                                throw new Error("not a directory: " + relPath);
                            }
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    LocalFileSystemCrudOnly.prototype.loadTextFile = function (relPath) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            return tslib_1.__generator(this, function (_a) {
                if (this.isIgnored(relPath)) {
                    throw new Error("Unable to read ignored path: '" + relPath + "'");
                }
                return [2 /*return*/, fs_extra_1.readFile(path.join(this.baseUrl, relPath), 'utf8')];
            });
        });
    };
    LocalFileSystemCrudOnly.prototype.loadDirectoryChildren = function (fullPath) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            var rootPath, pathPrefix, directoryChildren, processedChildren;
            return tslib_1.__generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (this.isIgnored(fullPath)) {
                            throw new Error("Unable to read ignored path: '" + fullPath + "'");
                        }
                        rootPath = path.join(this.baseUrl, fullPath);
                        pathPrefix = fullPath ? (fullPath + api_1.pathSeparator) : fullPath;
                        return [4 /*yield*/, fs_extra_1.readdir(rootPath)];
                    case 1:
                        directoryChildren = _a.sent();
                        return [4 /*yield*/, Promise.all(directoryChildren.map(function (item) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
                                var itemPath, itemAbsolutePath, itemStats;
                                return tslib_1.__generator(this, function (_a) {
                                    switch (_a.label) {
                                        case 0:
                                            itemPath = pathPrefix + item;
                                            itemAbsolutePath = path.join(rootPath, item);
                                            return [4 /*yield*/, fs_extra_1.stat(itemAbsolutePath)];
                                        case 1:
                                            itemStats = _a.sent();
                                            if (itemStats.isDirectory()) {
                                                return [2 /*return*/, new api_1.ShallowDirectory(item, itemPath)];
                                            }
                                            else if (itemStats.isFile()) {
                                                return [2 /*return*/, new api_1.File(item, itemPath)];
                                            }
                                            else {
                                                console.warn("Unknown node type at " + itemAbsolutePath);
                                                return [2 /*return*/, null];
                                            }
                                            return [2 /*return*/];
                                    }
                                });
                            }); }))];
                    case 2:
                        processedChildren = _a.sent();
                        return [2 /*return*/, processedChildren.filter(function (i) { return i !== null; })];
                }
            });
        });
    };
    LocalFileSystemCrudOnly.prototype.loadDirectoryTree = function (fullPath) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var _this = this;
            var memFs;
            return tslib_1.__generator(this, function (_a) {
                if (fullPath && this.isIgnored(fullPath)) {
                    throw new Error("Unable to read ignored path: '" + fullPath + "'");
                }
                memFs = new memory_fs_1.MemoryFileSystem();
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        var _a = _this, baseUrl = _a.baseUrl, isIgnored = _a.isIgnored;
                        var rootPath = fullPath ? path.join(baseUrl, fullPath) : baseUrl;
                        var walker = walk(rootPath);
                        walker.on('readable', function () {
                            var item;
                            while ((item = walker.read())) {
                                var itemPath = path.relative(baseUrl, item.path).split(path.sep).join(api_1.pathSeparator);
                                if (isIgnored(itemPath)) {
                                    return;
                                }
                                else if (item.stats.isDirectory()) {
                                    memFs.ensureDirectorySync(itemPath);
                                }
                                else if (item.stats.isFile()) {
                                    memFs.saveFileSync(itemPath, '');
                                }
                                else {
                                    console.warn("unknown node type at " + itemPath, item);
                                }
                            }
                        })
                            .on('end', function () {
                            resolve(memFs.loadDirectoryTreeSync(fullPath));
                        })
                            .on('error', reject);
                    })];
            });
        });
    };
    LocalFileSystemCrudOnly.prototype.ensureDirectory = function (relPath) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var pathArr, fullPath;
            return tslib_1.__generator(this, function (_a) {
                if (this.isIgnored(relPath)) {
                    throw new Error("Unable to read and write ignored path: '" + relPath + "'");
                }
                pathArr = utils_1.getPathNodes(relPath);
                fullPath = path.join.apply(path, [this.baseUrl].concat(pathArr));
                return [2 /*return*/, fs_extra_1.ensureDir(fullPath)];
            });
        });
    };
    return LocalFileSystemCrudOnly;
}());
exports.LocalFileSystemCrudOnly = LocalFileSystemCrudOnly;
//# sourceMappingURL=local-fs-crud-only.js.map