"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const schematics_1 = require("@angular-devkit/schematics");
const minimatch_1 = __importDefault(require("minimatch"));
const prettier_1 = require("prettier");
const rxjs_1 = require("rxjs");
const SKIP_GEN_CONFIG_FILE = '.iotizeskipgen';
const SUPPORTED_CODE_FORMAT_EXTENSION = {
    'css': ['css'],
    'typescript': ['ts'],
    'scss': ['scss'],
    'json': ['json'],
    'markdown': ['md'],
    'html': ['html'],
    'yaml': ['yaml', 'yml']
};
function getParserFromExtension(path) {
    let parser;
    for (parser in SUPPORTED_CODE_FORMAT_EXTENSION) {
        let extensions = SUPPORTED_CODE_FORMAT_EXTENSION[parser];
        for (let extension of extensions) {
            if (path.endsWith(`.${extension}`)) {
                return parser;
            }
        }
    }
    return undefined;
}
function codeFormatRule(tree, formatOptions = {}, overwrite) {
    return schematics_1.forEach((fileEntry) => {
        let parser = getParserFromExtension(fileEntry.path);
        if (!parser) {
            return fileEntry;
        }
        formatOptions.parser = parser;
        let formatedContent = prettier_1.format(fileEntry.content.toString(), formatOptions);
        if (tree.exists(fileEntry.path)) {
            if (!overwrite) {
                return fileEntry;
            }
            tree.overwrite(fileEntry.path, formatedContent);
        }
        else {
            tree.create(fileEntry.path, formatedContent);
        }
        return tree.get(fileEntry.path);
    });
}
exports.codeFormatRule = codeFormatRule;
// export function urlWithIgnore(urlString: string) {
//   const myUrl = parseUrl(urlString);
//   return (context: SchematicContext) => {
//     let sources = context.engine.createSourceFromUrl(myUrl, context)(context);
//     console.info('urlWithIgnore', sources);
//     return sources;
//   };
// }
function applyWithOverwriteRule(source, rules, options = {}) {
    if (options.overwrite === undefined) {
        options.overwrite = true;
    }
    if (options.format === undefined) {
        options.format = true;
    }
    return (tree, _context) => {
        const rule = schematics_1.mergeWith(schematics_1.apply(source, [
            ...rules,
            skipFileRule(tree, _context),
            options.format ? codeFormatRule(tree, options.format !== true ? options.format : {}, options.overwrite) : schematics_1.noop(),
            overwriteAllRule(tree, options.overwrite, options.ignoreIfExists)
        ]));
        return rule(tree, _context);
    };
}
exports.applyWithOverwriteRule = applyWithOverwriteRule;
function skipFileRule(tree, _context) {
    return schematics_1.forEach((entry) => {
        // _context.logger.warn(`test ${entry.path}`);
        let skipRules = getSkipRules(tree);
        if (shouldSkipFile(entry.path.substr(1), skipRules)) {
            _context.logger.warn(`SKIP ${entry.path}`);
            return null;
        }
        return entry;
    });
}
exports.skipFileRule = skipFileRule;
// export function forEachWithSkip(operator: FileOperator) {
//   return (tree: Tree, context: SchematicContext) => {
//     let skipRules = getSkipRules(tree);
//     tree.visit((path, entry) => {
//       console.info('Path', path);
//       if (!entry) {
//         return;
//       }
//       const newEntry = operator(entry);
//       if (newEntry === entry) {
//         return;
//       }
//       if (newEntry === null) {
//         tree.delete(path);
//         return;
//       }
//       if (newEntry.path != path) {
//         tree.rename(path, newEntry.path);
//       }
//       if (!newEntry.content.equals(entry.content)) {
//         tree.overwrite(newEntry.path, newEntry.content);
//       }
//     });
//     return tree;
//   }
// }
function overwriteAllRule(tree, overwrite, ignoreIfExists) {
    return schematics_1.forEach((fileEntry) => {
        // console.info('fileEntry', fileEntry.path, tree.exists(fileEntry.path), overwrite);
        if (tree.exists(fileEntry.path)) {
            if (overwrite) {
                tree.overwrite(fileEntry.path, fileEntry.content);
            }
            else if (ignoreIfExists) {
                return null;
            }
            else {
                // tree.create(fileEntry.path, fileEntry.content);
            }
        }
        return fileEntry;
    });
}
exports.overwriteAllRule = overwriteAllRule;
function getSkipRules(tree) {
    let skipRules = undefined;
    if (tree.exists(SKIP_GEN_CONFIG_FILE)) {
        let content = tree.read(SKIP_GEN_CONFIG_FILE).toString();
        // console.info('Skip rule: ', content);
        skipRules = content.split(/(?:\r\n|\r|\n)/g);
    }
    return skipRules;
}
function shouldSkipFile(filepath, skipRules) {
    if (skipRules && !Array.isArray(skipRules)) {
        skipRules = getSkipRules(skipRules);
    }
    if (skipRules) {
        // console.warn('test skip rules', filepath, skipRules);
        for (let glob of skipRules) {
            if (minimatch_1.default(glob, filepath)) {
                return true;
            }
        }
    }
    return false;
}
function applyRule(source, templateData, url = './') {
    return (tree, _context) => {
        const rule = schematics_1.mergeWith(schematics_1.apply(source, [
            schematics_1.template(templateData),
            schematics_1.move(url)
        ]));
        return rule(tree, _context);
    };
}
exports.applyRule = applyRule;
function toPromiseRule(cb) {
    return (tree, context) => {
        return rxjs_1.Observable.create(async (observer) => {
            try {
                await cb(tree, context);
                observer.next(tree);
                observer.complete();
            }
            catch (err) {
                observer.error(err);
            }
        });
    };
}
exports.toPromiseRule = toPromiseRule;
//# sourceMappingURL=index.js.map