"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 sp_loader_1 = require("@microsoft/sp-loader");
var sp_telemetry_1 = require("@ms/sp-telemetry");
var ApplicationLoadType_1 = require("./ApplicationLoadType");
var BaseApplication_1 = tslib_1.__importDefault(require("./BaseApplication"));
var OnBeforeNavigationEventName_1 = tslib_1.__importDefault(require("./navigator/OnBeforeNavigationEventName"));
var Navigator_1 = tslib_1.__importDefault(require("./navigator/Navigator"));
var strings = tslib_1.__importStar(require("./SPApplicationBase.resx"));
var DialogManagerConfiguration_1 = tslib_1.__importDefault(require("./extensibility/DialogManagerConfiguration"));
var Killswitches_1 = require("./common/Killswitches");
// Qos constants
var startQosScenarioName = 'ApplicationManager.start';
var initializeQosScenarioName = 'ApplicationManager.initialize';
var applicationFailedToLoadFailure = 'ApplicationFailedToLoad';
var shellStartFailure = 'SPShell.Start';
/**
 * Application manager. Includes logic to load SPFX client-side applications.
 * @internal
 */
var ApplicationManager = /** @class */ (function () {
    /**
     * Creates an application manager.
     * @param serviceScope - Root service scope.
     */
    function ApplicationManager(serviceScope, navigator) {
        sp_core_library_1.Validate.isNotNullOrUndefined(serviceScope, 'serviceScope');
        this._serviceScope = serviceScope;
        this._navigator = navigator || new Navigator_1.default(this._serviceScope, this);
    }
    /**
     * Returns true if the current application is a chromeless application.
     *
     * @privateRemarks
     * PageChrome, SuiteNav and application render do not apply to chromeless applications, like
     * Classic pages and ListView application, and should not be called.
     * This is a temporary fix to prevent page chrome DOM and styles from getting inserted into
     * the list view host application.
     *
     * However, to ensure an application is chromeless and has a minimal assembly,
     * BaseApplication._getPageChromeProvider should return undefined.
     *
     * @internal
     */
    ApplicationManager._isChromelessApplication = function (componentId) {
        return (sp_core_library_1.Environment.type === sp_core_library_1.EnvironmentType.ClassicSharePoint ||
            componentId === 'b1ab4aaa-f779-405c-8683-d3a750b5d18d' || // list view host
            componentId === 'c22967c0-666a-4f03-a8c4-545efb9183e1' // mee-bridge-application
        );
    };
    /**
     * Returns true if the current application is a themeless application.
     *
     * @privateRemarks
     * The difference between this function and _isChromelessApplication is we sometimes need to load theme, but nothing else
     * @internal
     */
    ApplicationManager._isThemelessApplication = function (componentId) {
        return ((Killswitches_1.Killswitches.isListViewThemelessKSActivated() &&
            componentId === 'b1ab4aaa-f779-405c-8683-d3a750b5d18d') || // list view host
            componentId === 'c22967c0-666a-4f03-a8c4-545efb9183e1' // mee-bridge-application
        );
    };
    Object.defineProperty(ApplicationManager.prototype, "currentApplicationId", {
        /**
         * Returns the currently loaded application.
         * Returns Guid.empty if no application is currently loaded.
         */
        get: function () {
            var appComponentId = this._currentApplication && this._currentApplication.componentId;
            return appComponentId ? sp_core_library_1.Guid.parse(appComponentId) : sp_core_library_1.Guid.empty;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(ApplicationManager.prototype, "currentApplication", {
        /**
         * Returns the currently loaded application.
         * Returns Guid.empty if no application is currently loaded.
         */
        get: function () {
            sp_core_library_1.Validate.isNotNullOrUndefined(this._currentApplication, 'currentApplication');
            return this._currentApplication;
        },
        enumerable: false,
        configurable: true
    });
    /**
     * Loads an application and starts its execution.
     *
     * @param preloadedData - Application preloaded data. Must include the application id.
     */
    ApplicationManager.prototype.startApplication = function (preloadedData) {
        var _this = this;
        try {
            sp_core_library_1.Validate.isNonemptyString(preloadedData.clientSideApplicationId, 'preloadedData.clientSideApplicationId');
        }
        catch (error) {
            return Promise.reject(error);
        }
        var qosMonitor = new sp_diagnostics_1._QosMonitor(startQosScenarioName);
        function error(message, failureId) {
            var err = new Error(message);
            sp_diagnostics_1._TraceLogger.logError(ApplicationManager._logSource, err);
            qosMonitor.writeUnexpectedFailure(failureId, err);
            throw err;
        }
        var applicationId = preloadedData.clientSideApplicationId;
        var appManifest = sp_loader_1.SPComponentLoader.tryGetManifestById(applicationId);
        var appComponent = !!appManifest
            ? sp_loader_1.SPComponentLoader.tryGetLoadedComponent(appManifest)
            : undefined;
        if (appComponent) {
            return this._initializeApplicationWithTelemetry(appComponent, applicationId, qosMonitor, error);
        }
        else {
            // Application was not loaded synchronously. Request loading the application.
            var appComponentPromise = this._loadApplicationComponent(applicationId, error);
            return appComponentPromise.then(function (application) {
                return _this._initializeApplicationWithTelemetry(application, applicationId, qosMonitor, error);
            });
        }
    };
    ApplicationManager.prototype._raiseOnBeforeNavigationEventName = function (fromAppId, toAppId) {
        sp_core_library_1._SPEventManager.instance.raiseEvent(BaseApplication_1.default._onBeforeNavigationEventName, new OnBeforeNavigationEventName_1.default(fromAppId, toAppId));
    };
    Object.defineProperty(ApplicationManager.prototype, "_applicationLoadType", {
        get: function () {
            return this._previousApplication
                ? ApplicationLoadType_1.ApplicationLoadType.InPlaceNavigation
                : ApplicationLoadType_1.ApplicationLoadType.FullPageLoad;
        },
        enumerable: false,
        configurable: true
    });
    ApplicationManager.prototype._initializeApplicationWithTelemetry = function (application, applicationId, qosMonitor, error) {
        sp_telemetry_1._PerformanceLogger.markApplicationStart();
        return this._initializeApplication(new application.default(), applicationId)
            .then(function (result) {
            qosMonitor.writeSuccess();
            return result;
        })
            .catch(function (e) {
            return error(sp_core_library_1.Text.format(strings.applicationFailedToInitializeError, e), shellStartFailure);
        });
    };
    /**
     * Loads the application, defined by the application id passed as input.
     * Rejects the promise if the application can't be loaded.
     */
    ApplicationManager.prototype._loadApplicationComponent = function (applicationId, error) {
        return sp_loader_1.SPComponentLoader.loadComponentById(applicationId).catch(function (e) {
            return error(sp_core_library_1.Text.format(strings.applicationFailedToLoadWithMessageError, applicationId, e.message), applicationFailedToLoadFailure);
        });
    };
    ApplicationManager.prototype._isChromelessApplication = function (applicationId) {
        return ApplicationManager._isChromelessApplication(applicationId);
    };
    ApplicationManager.prototype._isThemelessApplication = function (applicationId) {
        return ApplicationManager._isThemelessApplication(applicationId);
    };
    /**
     * Initializes the application.
     * It sets up the PageChrome and SuiteNav if necessary, initializes the application context
     * and renders the application if necessary.
     *
     * @param application - Application to initialize.
     * @param applicationId - Application component Id.
     *
     * @returns A promise
     */
    ApplicationManager.prototype._initializeApplication = function (application, applicationId) {
        var _this = this;
        // tslint:disable-next-line:no-string-literal
        if (application['__type'] !== 'BaseApplication') {
            return Promise.reject(new Error('The application is not a subclass of BaseApplication'));
        }
        var qosMonitor = new sp_diagnostics_1._QosMonitor(initializeQosScenarioName);
        var applicationManifest = sp_loader_1.SPComponentLoader.tryGetManifestById(applicationId);
        var qosApplicationData = {
            alias: application.alias || applicationManifest.alias,
            isInternal: applicationManifest.isInternal,
            manifestId: applicationManifest.id
        };
        if (this._currentApplication) {
            this._previousApplication = this._currentApplication;
        }
        this._currentApplication = application;
        if (this._previousApplication) {
            this._raiseOnBeforeNavigationEventName(this._previousApplication.componentId, applicationId);
            this._previousApplication._unload();
        }
        // Before initializing application customizers we should make sure that the page chrome is initialized.
        // Page chrome initializes the dialog manager.
        // This must run before calling Navigator.navigateToPreloadedData to ensure DialogManager is set up.
        var pageChromeProvider = this._currentApplication._getPageChromeProvider();
        var isChromelessApplication = this._isChromelessApplication(applicationId);
        if (!isChromelessApplication) {
            if (pageChromeProvider) {
                if (!this._masterChrome) {
                    this._masterChrome = pageChromeProvider.initializeMasterChrome();
                }
                if (!this._pageChrome) {
                    this._pageChrome = pageChromeProvider.initializePageChrome(this._serviceScope, this._masterChrome, applicationId);
                    // The default configuration for dialog manager. This may be changed by the application later.
                    // Note: This will not run if the application does not own the page chrome and hence must be called
                    // by the application if they choose to use the dialog manager.
                    DialogManagerConfiguration_1.default.instance.initialize(this._pageChrome.dialogContainerDiv);
                }
            }
        }
        try {
            return this._currentApplication
                ._load({
                manifest: applicationManifest,
                parentServiceScope: this._serviceScope,
                navigator: this._navigator,
                instanceId: applicationManifest.id,
                loggingTag: "Application." + applicationManifest.id,
                chrome: this._pageChrome,
                loadType: this._applicationLoadType
            })
                .then(function () {
                if (_this._previousApplication) {
                    _this._previousApplication.dispose();
                    _this._previousApplication = undefined;
                }
                if (pageChromeProvider) {
                    if (!_this._isThemelessApplication(applicationId)) {
                        _this._currentApplication._loadTheme();
                    }
                    if (!isChromelessApplication) {
                        _this._currentApplication._render();
                    }
                }
                qosMonitor.writeSuccess(qosApplicationData);
                return application;
            })
                .catch(function (e) {
                qosMonitor.writeUnexpectedFailure('AsyncError', e, qosApplicationData);
                return Promise.reject(e);
            });
        }
        catch (e) {
            qosMonitor.writeUnexpectedFailure('GeneralError', e, qosApplicationData);
            return Promise.reject(e);
        }
    };
    ApplicationManager._logSource = sp_diagnostics_1._LogSource.create('ApplicationManager');
    return ApplicationManager;
}());
exports.default = ApplicationManager;
//# sourceMappingURL=ApplicationManager.js.map