"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectInitializer = void 0;
const tslib_1 = require("tslib");
const fs = require("fs");
const path = require("path");
const nodeUtil = require("util");
const contracts_1 = require("@codiac.io/codiac-common/contracts");
const _1 = require(".");
const base_scaffolding_1 = require("./scaffolding/base-scaffolding");
const mkdirAsync = nodeUtil.promisify(fs.mkdir); // anitquated nastiness
const existsAsync = nodeUtil.promisify(fs.exists); // anitquated nastiness
/**
 *
 */
class ProjectInitializer {
    constructor(cliRoot, _ops, _cfgRepo, logger) {
        this._ops = _ops;
        this._cfgRepo = _cfgRepo;
        this.logger = logger;
        this.cliAssetsFolder = path.join(cliRoot, "scaffolding");
    }
    /**
     *
     * @param targetFolder Absolute or relative to the current working directory.  If clone url is specified, the repo will be cloned directly into this folder.
     * @param projectType The Codiac project type to scaffold.
     * @param cloneUrl Fully qualified clone url for the repo.  This url gets stored with the project.
     */
    init(targetFolder, projectType, cloneUrl) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    // change dir
                    // try {
                    //   process.chdir(targetFolder);
                    //   fs.mkdirSync(process.cwd());
                    // } catch (error) {
                    //   this.logger.error(`Error switching current working directory to ${targetFolder}: ${error.message||""}`, error);
                    // }
                    if (cloneUrl) {
                        yield this._ops.gitClone(cloneUrl, targetFolder);
                        // COMMENTED OUT BC:  git clone behavior differs from the defaults we should use here 
                        //                    (we want to default to current folder, like npm init does), 
                        //                    so instead of introducing wierdness or counter-intuitive defaults, 
                        //                    we made targetFolder a required argument, so it simply never defaults. 
                        // Derive the git project name fromthe repo url
                        // if (!targetFolder) {
                        //   const splits = cloneUrl.split('/');
                        //   destination = splits[splits.length - 1]
                        // }
                        this.logger.detail(`Cloned repo to target folder: ${path.resolve(targetFolder)}`);
                    }
                    else {
                        if (path.resolve(targetFolder) != process.cwd()) {
                            fs.mkdirSync(targetFolder);
                            this.logger.detail(`Created target folder: ${path.resolve(targetFolder)}`);
                        }
                    }
                    process.chdir(targetFolder);
                    let projectRoot = process.cwd();
                    // Commented out bc: This copmmand doesnt care whether we are in a repo or not.
                    // let repoRoot = await this._ops.getRepoRoot(projectRoot);  // NOTE this will throw if the folder isnt a repo
                    // this.logger.trace(`Repo root: ${repoRoot}`);
                    yield this._ops.tryOpenVsCode(projectRoot);
                    this._projectConfig = this._cfgRepo.writeNewProjectConfig();
                    // this.logger.detail('Added project config: ' + this.styler.hilite(projectRoot));
                    this.logger.detail('Added project config: ' + projectRoot);
                    let scaffolding = this.getScaffolding(projectType);
                    yield this.scaffoldProject(scaffolding, this._projectConfig);
                    resolve(new contracts_1.Result(true));
                }
                catch (err) {
                    reject(err);
                }
            }));
        });
    }
    /** Poor-man's ioc to get the project initializer.
     *
     * @param name (Optional: defaults to the base scaffolding) name of scaffolding package to initialize with.
     */
    getScaffolding(name) {
        switch (name) {
            case "api":
                return new _1.CodiacApiScaffolding(this.logger);
            case "typescript":
                return new _1.TypescriptScaffolding(this.logger);
            default:
                return new base_scaffolding_1.BaseScaffolding();
        }
    }
    // private getApiScaffolding(): Scaffolding {
    //   try {
    //     let scaf = new Scaffolding("api");
    //     scaf.npmDependencies = [
    //       "reflect-metadata",
    //       "@codiac.io/codiac-api-base",
    //       "@codiac.io/codiac-auth-contracts",
    //       "@codiac.io/codiac-common",
    //       "@codiac.io/plugins-auth-sdk",
    //       "@codiac.io/plugins-mongo-repo"
    //     ];
    //     scaf.npmDevDependencies = [
    //       "mocha",
    //       "chai",
    //       "nyc",
    //       "@types/mocha",
    //       "@types/chai",
    //       "@types/node",
    //       "ts-node",
    //       "typescript@4.0.5",
    //       'reflect-metadata'
    //     ];
    //     scaf.scaffoldFolders = [".vscode", "src"]
    //     scaf.scaffoldFiles = [
    //       `.gitignore${ProjectInitializer.SCAFFOLDING_SUFFIX}`,
    //       "src/app-config.json",
    //       `src/index.ts${ProjectInitializer.SCAFFOLDING_SUFFIX}`,
    //       `src/myApiDef.ts${ProjectInitializer.SCAFFOLDING_SUFFIX}`,
    //       ".vscode/settings.json",
    //       ".vscode/tasks.json",
    //       ".vscode/launch.json"
    //     ];
    //     scaf.sccIgnoreFile = `.gitignore${ProjectInitializer.SCAFFOLDING_SUFFIX}`;
    //     scaf.afterInitHandler = async config => {
    //       // Declare the api image
    //       let target = new RegistryTarget("default", ProjectInitializer.DEFAULT_REGISTRY_URL)
    //       this._ops.declareImageExport(<ProjectConfig>config, config.name, target, "Dockerfile", undefined);
    //     };
    //     return scaf;
    //   } catch (err) {
    //     // this.logger.error(err.message||`Error loading api scaffolding.`, err);
    //     throw err;
    //   }
    // }
    // private getTypescriptScaffolding(): Scaffolding {
    //   try {
    //     let scaf = new Scaffolding("default");
    //     scaf.npmDependencies = ["reflect-metadata"]
    //     scaf.npmDevDependencies = [
    //       "mocha",
    //       "chai",
    //       "nyc",
    //       "@types/mocha",
    //       "@types/chai",
    //       "@types/node",
    //       "ts-node",
    //       "typescript@3.8.3",
    //       'reflect-metadata'
    //     ];
    //     scaf.scaffoldFolders = [".vscode", "src"]
    //     scaf.scaffoldFiles = [
    //       `.gitignore${ProjectInitializer.SCAFFOLDING_SUFFIX}`,
    //       `src/index.ts${ProjectInitializer.SCAFFOLDING_SUFFIX}`,
    //       ".vscode/settings.json",
    //       ".vscode/tasks.json",
    //       ".vscode/launch.json"
    //     ];
    //     scaf.sccIgnoreFile = `.gitignore${ProjectInitializer.SCAFFOLDING_SUFFIX}`;
    //     // scaf.afterInitHandler = async config => {
    //     //   // Declare the api image
    //     //   let target = new RegistryTarget("default", ProjectInitializer.DEFAULT_REGISTRY_URL)
    //     //   this._ops.declareImageExport(<ProjectConfig>config, config.name, target, "Dockerfile", undefined);
    //     // };
    //     return scaf;
    //   } catch (err) {
    //     throw err;
    //   }
    // }
    /** Creates initial files and folders required for any api using the given scaffolding parameters. */
    scaffoldProject(scaffolding, projectConfig) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    this.logger.detail(`Scaffolding project as '${scaffolding.name}'...`);
                    let projectRoot = path.join(this._ops.getConfigRoot());
                    // this.logger.detail(`Assets folder: ${cliAssetsFolder}`)
                    // TODO:  Consiuder walking the assets folder instead of listing the assets in this._scaffoldFolders and this._scaffoldFiles
                    this.logger.detail("Initial folders...");
                    for (let index in scaffolding.scaffoldFolders) {
                        let relPath = scaffolding.scaffoldFolders[index];
                        let targetFolder = path.join(projectRoot, relPath);
                        if (!(yield existsAsync(targetFolder))) {
                            this.logger.detail(`Creating folder: ${relPath}`);
                            yield mkdirAsync(targetFolder);
                        }
                    }
                    this.logger.detail("Initial files...");
                    for (let index in scaffolding.scaffoldFiles) {
                        let relPath = scaffolding.scaffoldFiles[index];
                        let source = path.join(this.cliAssetsFolder, scaffolding.name, relPath);
                        let target = path.join(projectRoot, relPath);
                        if (target.endsWith(ProjectInitializer.SCAFFOLDING_SUFFIX)) {
                            target = target.substring(0, target.lastIndexOf(ProjectInitializer.SCAFFOLDING_SUFFIX));
                        }
                        this.logger.detail(`Creating file: ${relPath}`);
                        if (fs.existsSync(target)) {
                            fs.unlinkSync(target);
                        }
                        fs.copyFileSync(source, target);
                    }
                    if (scaffolding.afterInitHandler) {
                        this.logger.detail(`Executing after-init script...`);
                        yield scaffolding.afterInitHandler(projectRoot, projectConfig, this._ops);
                    }
                    yield this._cfgRepo.updateProjectConfigFile(projectConfig);
                    resolve();
                }
                catch (err) {
                    reject(err);
                }
            }));
        });
    }
}
exports.ProjectInitializer = ProjectInitializer;
ProjectInitializer.SCAFFOLDING_SUFFIX = "-scaffolding";
ProjectInitializer.DEFAULT_REGISTRY_URL = "https://index.docker.io/v1";
//# sourceMappingURL=project-initializer.js.map