"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 CReplacePlugin_1 = require("./CReplacePlugin");
const webpack = require("webpack");
const utils_1 = require("../model/utils");
const utils_2 = require("../utils");
const fs = require("fs");
const copyFiles = require("copyfiles");
const AbstractTypescriptCompiler_1 = require("./AbstractTypescriptCompiler");
const CplaceTSConfigGenerator_1 = require("../model/CplaceTSConfigGenerator");
class CplaceTypescriptCompiler extends AbstractTypescriptCompiler_1.AbstractTypescriptCompiler {
    constructor(pluginName, dependencyPaths, assetsPath, mainRepoDir, isProduction) {
        super(pluginName, dependencyPaths, assetsPath, mainRepoDir, isProduction, 'ts', CplaceTypescriptCompiler.DEST_DIR);
    }
    static getJavaScriptOutputDir(assetsPath) {
        return path.resolve(assetsPath, this.DEST_DIR);
    }
    getJobName() {
        return 'cplace TypeScript (UI)';
    }
    doPostProcessing() {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.copyStaticFiles();
            yield this.runWebpack();
        });
    }
    runWebpack() {
        return new Promise((resolve, reject) => {
            // remove previously generated webpack bundle if exists (so it does not append)
            const bundleFile = path.resolve(this.assetsPath, CplaceTypescriptCompiler.DEST_DIR, 'tsc.js');
            if (fs.existsSync(bundleFile)) {
                fs.unlinkSync(bundleFile);
            }
            // @ts-ignore
            webpack(this.getWebpackConfig(), (err, stats) => {
                if (err) {
                    reject(err);
                }
                else if (stats.hasErrors()) {
                    throw Error(stats.toString());
                }
                else {
                    resolve();
                }
            });
        });
    }
    getWebpackConfig() {
        const config = {
            context: path.resolve(this.assetsPath, CplaceTypescriptCompiler.DEST_DIR),
            entry: {
                tsc: './' + CplaceTypescriptCompiler.ENTRY
            },
            externals: this.populateWebpackExternals(),
            mode: 'development',
            module: {
                rules: [
                    {
                        test: /\.js$/,
                        exclude: /node_modules/,
                        use: [{
                                loader: path.resolve(__filename, '../contextInjectorLoader.js'),
                                options: {
                                    entry: CplaceTypescriptCompiler.ENTRY
                                }
                            }]
                    },
                    {
                        test: new RegExp(`\.(${CplaceTypescriptCompiler.STATIC_IMPORT_EXTENSIONS})$`),
                        use: [{
                                loader: path.resolve(__filename, '../../../node_modules/raw-loader')
                            }]
                    }
                ]
            },
            output: {
                filename: '[name].js',
                path: path.resolve(this.assetsPath, CplaceTypescriptCompiler.DEST_DIR),
                pathinfo: true,
                /**
                 * The plugin will be exported as a webpackContext with exported name in the app.ts.
                 * This gives us the capability to (globally) resolve all given module.
                 * @link https://webpack.js.org/guides/dependency-management/#require-context
                 * @link https://webpack.js.org/configuration/output/
                 */
                library: '$' + this.pluginName.replace(/\./g, '_'),
                libraryExport: 'default'
            },
            plugins: [
                new CReplacePlugin_1.CReplacePlugin()
            ],
            resolve: {
                extensions: ['.ts', '.js']
            }
        };
        if (!this.isProduction) {
            config.devtool = 'source-map';
            // @ts-ignore
            config.module.rules.push({
                test: /\.js$/,
                exclude: /node_modules/,
                use: [{
                        loader: path.resolve(__filename, '../../../node_modules/source-map-loader')
                    }],
                enforce: 'pre'
            });
        }
        return config;
    }
    populateWebpackExternals() {
        const pluginDir = path.dirname(this.assetsPath);
        const extraTypes = CplaceTSConfigGenerator_1.CplaceTSConfigGenerator.getExtraTypes(pluginDir, this.dependencyPaths);
        return [Object.assign({}, CplaceTypescriptCompiler.DEFAULT_EXTERNALS, (extraTypes ? extraTypes.externals : {})), this.resolveWebpackExternal.bind(this)];
    }
    resolveWebpackExternal(context, request, callback) {
        if (utils_1.isFromLibrary(request)) {
            const newRequest = request.substr(1);
            return callback(null, newRequest);
        }
        callback();
    }
    copyStaticFiles() {
        return __awaiter(this, void 0, void 0, function* () {
            const tsAssetsPath = path.resolve(this.assetsPath, 'ts');
            const srcGlob = `${tsAssetsPath}/**/*.+(${CplaceTypescriptCompiler.STATIC_IMPORT_EXTENSIONS})`;
            const dest = path.resolve(this.assetsPath, CplaceTypescriptCompiler.DEST_DIR) + path.sep;
            const upLength = tsAssetsPath.split(path.sep).length;
            const options = {
                up: upLength,
                verbose: utils_2.isDebugEnabled()
            };
            utils_2.debug(`(TypescriptCompiler) [${this.pluginName}] copying static files...`);
            return new Promise((resolve, reject) => {
                copyFiles([srcGlob, dest], options, (error) => {
                    if (error) {
                        reject(error);
                    }
                    else {
                        resolve();
                    }
                });
            });
        });
    }
}
CplaceTypescriptCompiler.DEST_DIR = 'generated_js';
CplaceTypescriptCompiler.ENTRY = 'app.js';
CplaceTypescriptCompiler.STATIC_IMPORT_EXTENSIONS = 'html|htm';
CplaceTypescriptCompiler.DEFAULT_EXTERNALS = {
    d3: 'd3',
    moment: 'moment',
    underscore: '_',
    draggable: 'Draggable'
};
exports.CplaceTypescriptCompiler = CplaceTypescriptCompiler;
//# sourceMappingURL=CplaceTypescriptCompiler.js.map