"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.IgniteUIForAngularTemplate = void 0;
const cli_core_1 = require("@igniteui/cli-core");
const path = __importStar(require("path"));
class IgniteUIForAngularTemplate {
    get templatePaths() {
        return [path.join(this.rootPath, "files")];
    }
    constructor(rootPath) {
        this.rootPath = rootPath;
        this.listInComponentTemplates = true;
        this.addAsNgModuleDeclaration = false;
        this.addAsNgModuleImport = true;
        this.listInCustomTemplates = false;
        this.framework = "angular";
        this.projectType = "igx-ts";
        this.hasExtraConfiguration = false;
        this.isHidden = false;
        this.packages = [];
        this.dependencies = [];
        this.delimiters = {
            content: {
                end: `%>`,
                start: `<%=`
            },
            path: {
                end: `__`,
                start: `__`
            }
        };
    }
    generateConfig(name, options) {
        if (options["modulePath"] && !cli_core_1.Util.fileExists(path.join(process.cwd(), `src\\app`, options["modulePath"]))) {
            cli_core_1.Util.error(`Wrong module path provided: ${options["modulePath"]}. No components were added!`);
            return Promise.resolve(false);
        }
        return Object.assign({}, options["extraConfig"], this.getBaseVariables(name));
    }
    //TODO: rename name to fullName for clarity + in all other places fileName to fullName
    registerInProject(projectPath, name, options) {
        let modulePath = "app-module.ts";
        if (options && options.modulePath) {
            modulePath = options.modulePath;
        }
        // D.P. Don't use the top-level import as that chains import of typescript
        // which slows down execution of the entire component noticeably (template loading)
        // https://www.typescriptlang.org/docs/handbook/modules.html#dynamic-module-loading-in-nodejs
        const TsUpdate = require("./AngularTypeScriptFileUpdate").AngularTypeScriptFileUpdate;
        const mainModulePath = path.join(projectPath, `src/app/${modulePath}`);
        const folderName = this.folderName(name);
        const fileName = this.fileName(name);
        const componentFilePath = path.join(projectPath, `src/app/${folderName}/${fileName}.ts`);
        const className = `${cli_core_1.Util.className(cli_core_1.Util.nameFromPath(name))}`;
        // standalone components
        if (!this.fileExists(mainModulePath)) {
            const appRoutesPath = "src/app/app.routes.ts";
            if (!(options && options.skipRoute) && this.fileExists(appRoutesPath)) {
                const routesConfigPath = path.join(projectPath, appRoutesPath);
                const rountesConfig = new TsUpdate(routesConfigPath, true, { indentSize: 2, singleQuotes: true });
                rountesConfig.addRoute({
                    modulePath: cli_core_1.Util.relativePath(routesConfigPath, componentFilePath, true, true),
                    path: this.fileName(name),
                    data: { text: cli_core_1.Util.nameFromPath(name) },
                    identifierName: className
                });
                rountesConfig.finalize();
            }
            const componentFile = new TsUpdate(componentFilePath, true, { indentSize: 2, singleQuotes: true });
            for (const dep of this.dependencies) {
                if (dep.from && dep.from.startsWith(".")) {
                    // relative file dependency
                    const copy = Object.assign({}, dep);
                    copy.from = cli_core_1.Util.relativePath(componentFilePath, path.join(projectPath, copy.from), true, true);
                    componentFile.addStandaloneComponentMeta(dep, cli_core_1.Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content));
                    continue;
                }
                componentFile.addStandaloneComponentMeta(dep, cli_core_1.Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content));
            }
            componentFile.finalize();
            return;
        }
        // ngModule based components
        if (!(options && options.skipRoute) && this.fileExists("src/app/app-routing-module.ts")) {
            //1) import the component class name,
            //2) and populate the Routes array with the path and component
            //for example: { path: 'combo', component: ComboComponent }
            const routingModulePath = path.join(projectPath, "src/app/app-routing-module.ts");
            const routingModule = new TsUpdate(routingModulePath, false, { indentSize: 2, singleQuotes: true });
            routingModule.addRoute({
                modulePath: cli_core_1.Util.relativePath(routingModulePath, componentFilePath, true, true),
                path: this.fileName(name),
                data: { text: cli_core_1.Util.nameFromPath(name) },
                identifierName: className
            });
            routingModule.finalize();
        }
        //3) add an import of the component class from its file location.
        //4) populate the declarations portion of the @NgModule with the component class name.
        const mainModule = new TsUpdate(mainModulePath, false, { indentSize: 2, singleQuotes: true });
        mainModule.addNgModuleMeta({
            declare: this.addAsNgModuleDeclaration ? [className] : [],
            import: this.addAsNgModuleImport ? [className] : [],
            from: cli_core_1.Util.relativePath(mainModulePath, componentFilePath, true, true),
            export: modulePath !== "app-module.ts" ? [className] : []
        }, cli_core_1.Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content), true // multiline
        );
        // import IgxModules and other dependencies
        for (const dep of this.dependencies) {
            if (dep.from && dep.from.startsWith(".")) {
                // relative file dependency
                const copy = Object.assign({}, dep);
                copy.from = cli_core_1.Util.relativePath(mainModulePath, path.join(projectPath, copy.from), true, true);
                mainModule.addNgModuleMeta(copy, cli_core_1.Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content), true // multiline
                );
            }
            else {
                mainModule.addNgModuleMeta(dep, cli_core_1.Util.applyDelimiters(this.getBaseVariables(name), this.delimiters.content), true // multiline
                );
            }
        }
        mainModule.finalize();
    }
    getExtraConfiguration() {
        return [];
    }
    setExtraConfiguration(extraConfigKeys) { }
    fileExists(filePath) {
        return cli_core_1.App.container.get(cli_core_1.FS_TOKEN).fileExists(filePath);
    }
    getBaseVariables(name) {
        const config = {};
        config["name"] = cli_core_1.Util.nameFromPath(name);
        config["ClassName"] = cli_core_1.Util.className(cli_core_1.Util.nameFromPath(name));
        config["path"] = this.folderName(name);
        config["filePrefix"] = this.fileName(name);
        config["description"] = this.description;
        config["cliVersion"] = cli_core_1.Util.version();
        config["camelCaseName"] = cli_core_1.Util.camelCase(name);
        config["igxPackage"] = (0, cli_core_1.resolvePackage)(cli_core_1.NPM_ANGULAR);
        config["dockManagerPackage"] = (0, cli_core_1.resolvePackage)(cli_core_1.NPM_DOCK_MANAGER);
        /** 'nameMerged' is never used igx templates, removed */
        return config;
    }
    folderName(pathName) {
        //TODO: should remove the spaces
        const parts = path.parse(pathName);
        let folderName = pathName;
        if (parts.dir) {
            folderName = path.join(parts.dir, parts.name);
            folderName = folderName.replace(/\\/g, "/");
            // TODO: config-based "src/app"?
            const relative = path.join(process.cwd(), "src/app", folderName);
            // path.join will also resolve any '..' segments
            // so if relative result doesn't start with CWD it's out of project root
            if (!relative.startsWith(process.cwd())) {
                cli_core_1.Util.error(`Path ${"src/app/" + folderName} is not valid!`, "red");
                process.exit(1);
            }
            //clean up potential leading spaces in folder names (`path/    name`):
            folderName = folderName.replace(/\/\s+/g, "/");
        }
        return cli_core_1.Util.lowerDashed(folderName);
    }
    fileName(pathName) {
        const name = cli_core_1.Util.nameFromPath(pathName);
        return cli_core_1.Util.lowerDashed(name);
    }
}
exports.IgniteUIForAngularTemplate = IgniteUIForAngularTemplate;
