"use strict";
/*
 * Copyright 2018, collaboration Factory AG. All rights reserved.
 */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fs = require("fs");
const glob = require("glob");
const CplaceTSConfigGenerator_1 = require("./CplaceTSConfigGenerator");
const utils_1 = require("../utils");
const rimraf = require("rimraf");
const CplaceTypescriptCompiler_1 = require("../compiler/CplaceTypescriptCompiler");
const CompressCssCompiler_1 = require("../compiler/CompressCssCompiler");
const E2ETSConfigGenerator_1 = require("./E2ETSConfigGenerator");
const DependencyParser_1 = require("./DependencyParser");
const NPMResolver_1 = require("./NPMResolver");
/**
 * Represents a cplace plugin that needs to be compiled
 */
class CplacePlugin {
    constructor(pluginName, pluginDir) {
        this.pluginName = pluginName;
        this.pluginDir = pluginDir;
        this.dependencies = [];
        this.dependents = [];
        this.repo = path.basename(path.dirname(path.resolve(pluginDir)));
        this.assetsDir = CplacePlugin.getAssetsDir(this.pluginDir);
        this.hasTypeScriptAssets = fs.existsSync(path.resolve(this.assetsDir, 'ts', 'app.ts'));
        this.hasTypeScriptE2EAssets = false;
        const e2ePath = path.resolve(this.assetsDir, 'e2e');
        if (fs.existsSync(e2ePath)) {
            this.hasTypeScriptE2EAssets = glob.sync(path.join(e2ePath, '**', '*.ts')).length > 0;
        }
        this.hasOpenAPIYamlAssets = glob.sync(path.join(this.pluginDir, 'api', '*.yaml')).length > 0;
        this.hasLessAssets = glob.sync(path.join(this.assetsDir, '**', '*.less'), { ignore: path.join(this.assetsDir, 'node_modules', '**', '*.less') }).length > 0;
        this.hasVendors = fs.existsSync(path.resolve(this.assetsDir, 'package.json'));
        this.hasCompressCssAssets = fs.existsSync(path.resolve(this.assetsDir, 'css', CompressCssCompiler_1.CompressCssCompiler.ENTRY_FILE_NAME));
    }
    static getAssetsDir(pluginDir) {
        return path.resolve(pluginDir, 'assets');
    }
    static getPluginPathRelativeToRepo(sourceRepo, targetPluginName, targetRepo, localOnly) {
        if (localOnly || sourceRepo === targetRepo) {
            return targetPluginName;
        }
        else {
            return path.join('..', targetRepo, targetPluginName);
        }
    }
    getPluginPathRelativeFromRepo(sourceRepo, localOnly) {
        return CplacePlugin.getPluginPathRelativeToRepo(sourceRepo, this.pluginName, this.repo, localOnly);
    }
    generateTsConfig(pluginResolver, isProduction, localOnly) {
        if (!this.hasTypeScriptAssets) {
            throw Error(`[${this.pluginName}] plugin does not have TypeScript assets`);
        }
        const dependenciesWithTypeScript = this.dependencies
            .map(pluginName => {
            const plugin = pluginResolver(pluginName);
            if (!plugin) {
                throw Error(`[${this.pluginName}] could not resolve dependency ${this.pluginName}`);
            }
            return plugin;
        })
            .filter(p => p.hasTypeScriptAssets);
        const tsConfigGenerator = new CplaceTSConfigGenerator_1.CplaceTSConfigGenerator(this, dependenciesWithTypeScript, localOnly, isProduction);
        const tsconfigPath = tsConfigGenerator.createConfigAndGetPath();
        if (!fs.existsSync(tsconfigPath)) {
            console.error(utils_1.cerr `[${this.pluginName}] Could not generate tsconfig file...`);
            throw Error(`[${this.pluginName}] tsconfig generation failed`);
        }
        else {
            console.log(`${utils_1.GREEN_CHECK} [${this.pluginName}] wrote tsconfig...`);
        }
    }
    generateTsE2EConfig(pluginResolver, isProduction, localOnly) {
        if (!this.hasTypeScriptE2EAssets) {
            throw Error(`[${this.pluginName}] plugin does not have TypeScript E2E assets`);
        }
        const dependenciesWithE2ETypeScript = this.dependencies
            .map(pluginName => {
            const plugin = pluginResolver(pluginName);
            if (!plugin) {
                throw Error(`[${this.pluginName}] could not resolve dependency ${this.pluginName}`);
            }
            return plugin;
        })
            .filter(p => p.hasTypeScriptE2EAssets);
        const tsConfigGenerator = new E2ETSConfigGenerator_1.E2ETSConfigGenerator(this, dependenciesWithE2ETypeScript, localOnly, isProduction);
        const tsconfigPath = tsConfigGenerator.createConfigAndGetPath();
        if (!fs.existsSync(tsconfigPath)) {
            console.error(utils_1.cerr `[${this.pluginName}] Could not generate tsconfig E2E file...`);
            throw Error(`[${this.pluginName}] tsconfig E2E generation failed`);
        }
        else {
            console.log(`${utils_1.GREEN_CHECK} [${this.pluginName}] wrote tsconfig E2E...`);
        }
    }
    cleanGeneratedOutput() {
        return __awaiter(this, void 0, void 0, function* () {
            const promises = [];
            if (this.hasLessAssets || this.hasCompressCssAssets) {
                const generatedCss = CompressCssCompiler_1.CompressCssCompiler.getCssOutputDir(this.assetsDir);
                promises.push(this.removeDir(generatedCss));
            }
            if (this.hasTypeScriptAssets) {
                const generatedJs = CplaceTypescriptCompiler_1.CplaceTypescriptCompiler.getJavaScriptOutputDir(this.assetsDir);
                promises.push(this.removeDir(generatedJs));
            }
            if (this.hasVendors) {
                const pluginNodeModules = NPMResolver_1.NPMResolver.getPluginNodeModulesPath(this.assetsDir);
                promises.push(this.removeDir(pluginNodeModules));
            }
            yield Promise.all(promises);
            if (promises.length) {
                console.log(`${utils_1.GREEN_CHECK} [${this.pluginName}] cleaned output directories`);
            }
        });
    }
    parseDependencies(excludeTestDependencies = false) {
        DependencyParser_1.getDependencyParser()
            .getPluginDependencies(this.pluginDir, this.pluginName, excludeTestDependencies)
            .forEach(dependency => this.dependencies.push(dependency));
    }
    removeDir(path) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => {
                rimraf(path, e => {
                    if (!e) {
                        utils_1.debug(`(CplacePlugin) [${this.pluginName}] removed folder ${path}`);
                        resolve();
                    }
                    else {
                        reject(e);
                    }
                });
            });
        });
    }
}
exports.default = CplacePlugin;
//# sourceMappingURL=CplacePlugin.js.map