"use strict";
/*
 * Copyright 2018, collaboration Factory AG. All rights reserved.
 */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(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 NPMResolver_1 = require("./NPMResolver");
const DescriptorParser_1 = require("./DescriptorParser");
const CombineJavascriptsCompiler_1 = require("../compiler/CombineJavascriptsCompiler");
const PluginPackageJsonGenerator_1 = require("./PluginPackageJsonGenerator");
/**
 * Represents a cplace plugin that needs to be compiled
 */
class CplacePlugin {
    constructor(pluginName, pluginDir, production) {
        this.pluginName = pluginName;
        this.pluginDir = pluginDir;
        this.production = production;
        this.dependents = [];
        this.pluginDescriptor = this.parsePluginDescriptor(production);
        this.repo = path.basename(path.dirname(path.resolve(pluginDir)));
        this.assetsDir = CplacePlugin.getAssetsDir(this.pluginDir);
        this.hasAssetsFolder = fs.existsSync(path.resolve(this.assetsDir));
        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));
        this.hasCombineJs = fs.existsSync(path.resolve(this.assetsDir, CombineJavascriptsCompiler_1.CombineJavascriptsCompiler.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.pluginDescriptor.dependencies
            .map((pluginDescriptor) => {
            const plugin = pluginResolver(pluginDescriptor.name);
            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...`);
        }
    }
    /**
     * Generate empty package.json file (only name and version) in assets folder for publishing purposes.
     */
    generatePackageJson(repositoryDir) {
        if (!this.hasAssetsFolder) {
            console.log(utils_1.cgreen `⇢`, `[${this.pluginName}] plugin does not have assets`);
            return;
        }
        const packageJsonGenerator = new PluginPackageJsonGenerator_1.PluginPackageJsonGenerator(this, repositoryDir);
        const packageJsonPath = packageJsonGenerator.generatePackageJson();
        if (!fs.existsSync(packageJsonPath)) {
            console.error(utils_1.cerr `[${this.pluginName}] Could not generate package.json file...`);
            throw Error(`[${this.pluginName}] package.json generation failed`);
        }
        else {
            console.log(`${utils_1.GREEN_CHECK} [${this.pluginName}] wrote package.json`);
        }
    }
    generateTsE2EConfig(pluginResolver, isProduction, localOnly) {
        if (!this.hasTypeScriptE2EAssets) {
            throw Error(`[${this.pluginName}] plugin does not have TypeScript E2E assets`);
        }
        const dependenciesWithE2ETypeScript = this.pluginDescriptor.dependencies
            .map((pluginDescriptor) => {
            const plugin = pluginResolver(pluginDescriptor.name);
            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));
            }
            if (this.hasCombineJs) {
                const generatedDir = CombineJavascriptsCompiler_1.CombineJavascriptsCompiler.getOutputDir(this.assetsDir);
                promises.push(this.removeDir(generatedDir));
            }
            yield Promise.all(promises);
            if (promises.length) {
                console.log(`${utils_1.GREEN_CHECK} [${this.pluginName}] cleaned output directories`);
            }
        });
    }
    parsePluginDescriptor(excludeTestDependencies = false) {
        return DescriptorParser_1.getDescriptorParser(this.pluginDir, this.pluginName, excludeTestDependencies).getPluginDescriptor();
    }
    static isCplacePluginWithGradleAndContainsPluginDescriptor(pluginDir) {
        return (fs.existsSync(this.getPathToDescriptor(pluginDir)) &&
            fs.existsSync(this.getPathToBuildGradle(pluginDir)));
    }
    static getPathToDescriptor(pluginDir) {
        return path.join(pluginDir, CplacePlugin.DESCRIPTOR_FILE_NAME);
    }
    static getPathToBuildGradle(pluginDir) {
        return path.join(pluginDir, CplacePlugin.BUILD_GRADLE_FILE_NAME);
    }
    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 {
                        console.error(utils_1.cerr `(CplacePlugin) [${this.pluginName}] cannot remove path ${path}. ${e}`);
                        reject(e);
                    }
                });
            });
        });
    }
}
exports.default = CplacePlugin;
CplacePlugin.DESCRIPTOR_FILE_NAME = 'pluginDescriptor.json';
CplacePlugin.BUILD_GRADLE_FILE_NAME = 'build.gradle';
//# sourceMappingURL=CplacePlugin.js.map