"use strict";
// Copyright (c) Microsoft. All rights reserved.
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var sp_core_library_1 = require("@microsoft/sp-core-library");
var sp_diagnostics_1 = require("@microsoft/sp-diagnostics");
var ErrorBuilder_1 = tslib_1.__importDefault(require("../error/ErrorBuilder"));
var SPLoaderError_1 = tslib_1.__importDefault(require("../error/SPLoaderError"));
var BaseComponentLoader_1 = require("../loader/BaseComponentLoader");
var loadComponent_1 = tslib_1.__importDefault(require("../loader/loadComponent"));
var ComponentStore_1 = tslib_1.__importDefault(require("../stores/ComponentStore"));
var ComponentOverrider_1 = tslib_1.__importDefault(require("../utilities/ComponentOverrider"));
var telemetryConstants = tslib_1.__importStar(require("../utilities/telemetryConstants"));
var SystemJsLoader_1 = tslib_1.__importDefault(require("./SystemJsLoader"));
/**
 * The component loader for SPFx.
 * This implementation uses SystemJS as the internal module loader.
 *
 * @alpha
 */
var SPSystemJsComponentLoader = /** @class */ (function (_super) {
    tslib_1.__extends(SPSystemJsComponentLoader, _super);
    // Initialization
    /**
     * @internal
     */
    function SPSystemJsComponentLoader(serviceScope) {
        var _this = _super.call(this, serviceScope) || this;
        _this._systemJsLoader = serviceScope.consume(SystemJsLoader_1.default.serviceKey);
        return _this;
    }
    // Public API
    /**
     * Given a URL, load a script.
     *
     * @param url     - The script URL.
     * @param options - globalExportsName: If the script isn't an AMD module and loads a global member on the page,
     *                    specify the global member's name.
     * @returns         A promise containing the loaded module.
     */
    SPSystemJsComponentLoader.prototype.loadScript = function (url, options) {
        sp_core_library_1.Validate.isNonemptyString(url, 'url');
        if (typeof options === 'string') {
            throw ErrorBuilder_1.default.buildLoadScriptWithStringError();
        }
        var globalMetaConfig = {
            meta: {}
        };
        // This ensures that SystemJS can execute a script that doesn't have any output
        globalMetaConfig.meta[url] = {
            scriptLoad: false
        };
        if (options) {
            if (options.globalExportsName) {
                globalMetaConfig.meta[url] = {
                    format: 'global',
                    exports: options.globalExportsName
                };
            }
        }
        this._systemJsLoader.systemConfig(globalMetaConfig);
        return this._systemJsLoader.systemImport(url);
    };
    /**
     * Loads a component from a manifest.
     *
     * @param manifest - Manifest of the module to load.
     * @returns          A promise containing the loaded module.
     */
    SPSystemJsComponentLoader.prototype.loadComponent = function (manifest) {
        var _this = this;
        var qosMonitor;
        var qosExtraData;
        if (!manifest.isInternal) {
            qosMonitor = new sp_diagnostics_1._QosMonitor(telemetryConstants.loadComponentQosScenarioName);
            qosExtraData = this._buildQosExtraData(manifest);
        }
        return loadComponent_1.default(manifest, this._systemJsLoader)
            .then(function (component) {
            if (qosMonitor) {
                qosMonitor.writeSuccess(qosExtraData);
            }
            return component;
        })
            .catch(function (error) {
            return _this._handleLoadComponentError(error, manifest, qosMonitor, qosExtraData);
        });
    };
    SPSystemJsComponentLoader.prototype._overrideComponent = function (componentId, componentModule) {
        ComponentOverrider_1.default.overrideComponent(componentId, componentModule, this._serviceScope, SystemJsLoader_1.default.serviceKey);
    };
    SPSystemJsComponentLoader.prototype._unloadComponent = function (manifest) {
        if (ComponentStore_1.default.instance.tryGetComponent(manifest.id, manifest.version)) {
            ComponentStore_1.default.instance.deleteComponent(manifest.id, manifest.version);
            this._systemJsLoader.systemDelete(manifest);
        }
    };
    /**
     * Workaround for ListView host app, as there are problems when using SystemJS and RequireJS together.
     * By configuring SystemJS scriptLoad = false it ensures that the "define" definition in the window is
     * the one from RequireJS
     * @override
     */
    SPSystemJsComponentLoader.prototype._listViewHostWorkaround = function (preloadedData) {
        if (preloadedData.clientSideApplicationId === 'b1ab4aaa-f779-405c-8683-d3a750b5d18d') {
            this._systemJsLoader._baseSystemConfig(SystemJsLoader_1.default.pluginName, /* scriptLoad */ false);
        }
    };
    SPSystemJsComponentLoader.prototype._buildQosExtraData = function (manifest) {
        return {
            manifestId: manifest.id,
            version: manifest.version,
            alias: manifest.alias,
            isInternal: manifest.isInternal,
            isDebug: manifest._isDebug,
            loader: 'systemjs'
        };
    };
    SPSystemJsComponentLoader.prototype._handleLoadComponentError = function (error, manifest, qosMonitor, qosExtraData) {
        if (error instanceof SPLoaderError_1.default && error.isExpected && qosMonitor) {
            qosMonitor.writeExpectedFailure(undefined, error, qosExtraData);
        }
        else if (qosMonitor) {
            qosMonitor.writeUnexpectedFailure(undefined, error, qosExtraData);
        }
        // If it fails to load, the caller can then call loadComponent() again and not hit the cache
        ComponentStore_1.default.instance.deleteComponent(manifest.id, manifest.version);
        throw error;
    };
    return SPSystemJsComponentLoader;
}(BaseComponentLoader_1.BaseComponentLoader));
exports.default = SPSystemJsComponentLoader;
//# sourceMappingURL=SPSystemJsComponentLoader.js.map