import { Compiler, Injectable, Optional } from '@angular/core';
const /** @type {?} */ FACTORY_CLASS_SUFFIX = 'NgFactory';
/**
 * Configuration for NgModuleLoader.
 * token.
 *
 * \@experimental
 * @abstract
 */
export class NgModuleLoaderConfig {
}
function NgModuleLoaderConfig_tsickle_Closure_declarations() {
    /**
     * Prefix to add when computing the name of the factory module for a given module name.
     * @type {?}
     */
    NgModuleLoaderConfig.prototype.factoryPathPrefix;
    /**
     * Suffix to add when computing the name of the factory module for a given module name.
     * @type {?}
     */
    NgModuleLoaderConfig.prototype.factoryPathSuffix;
}
const /** @type {?} */ DEFAULT_CONFIG = {
    factoryPathPrefix: '',
    factoryPathSuffix: '.ngfactory',
};
/**
 * NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
 */
export class NgModuleLoader {
    /**
     * @param {?} _compiler
     * @param {?=} config
     */
    constructor(_compiler, config) {
        this._compiler = _compiler;
        this._config = config || DEFAULT_CONFIG;
    }
    /**
     * @param {?} modulePath
     * @param {?} ngModuleExport
     * @return {?}
     */
    load(modulePath, ngModuleExport) {
        const /** @type {?} */ offlineMode = this._compiler instanceof Compiler;
        return offlineMode ? loadPrecompiledFactory(this._config, modulePath, ngModuleExport) : loadAndCompile(this._compiler, modulePath, ngModuleExport);
    }
}
NgModuleLoader.decorators = [
    { type: Injectable },
];
/**
 * @nocollapse
 */
NgModuleLoader.ctorParameters = () => [
    { type: Compiler, },
    { type: NgModuleLoaderConfig, decorators: [{ type: Optional },] },
];
function NgModuleLoader_tsickle_Closure_declarations() {
    /** @type {?} */
    NgModuleLoader.decorators;
    /**
     * @nocollapse
     * @type {?}
     */
    NgModuleLoader.ctorParameters;
    /** @type {?} */
    NgModuleLoader.prototype._config;
    /** @type {?} */
    NgModuleLoader.prototype._compiler;
}
/**
 * @param {?} compiler
 * @param {?} modulePath
 * @param {?} ngModuleExport
 * @return {?}
 */
function loadAndCompile(compiler, modulePath, ngModuleExport) {
    if (!ngModuleExport) {
        ngModuleExport = 'default';
    }
    return System.import(modulePath)
        .then((rawModule) => {
        const /** @type {?} */ module = rawModule[ngModuleExport];
        if (!module) {
            throw new Error(`Module ${modulePath} does not export ${ngModuleExport}`);
        }
        return compiler.compileModuleAsync(module);
    });
}
/**
 * @param {?} config
 * @param {?} modulePath
 * @param {?} ngModuleExport
 * @return {?}
 */
function loadPrecompiledFactory(config, modulePath, ngModuleExport) {
    let /** @type {?} */ factoryClassSuffix = FACTORY_CLASS_SUFFIX;
    if (ngModuleExport === undefined) {
        ngModuleExport = 'default';
        factoryClassSuffix = '';
    }
    return System.import(config.factoryPathPrefix + modulePath + config.factoryPathSuffix)
        .then((rawModule) => {
        const /** @type {?} */ ngModuleFactory = rawModule[ngModuleExport + factoryClassSuffix];
        if (!ngModuleFactory) {
            throw new Error(`Module ${modulePath} does not export ${ngModuleExport}`);
        }
        return ngModuleFactory;
    });
}
//# sourceMappingURL=ng-module-loader.js.map