"use strict";
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_extension_base_1 = require("@microsoft/sp-extension-base");
var sp_loader_1 = require("@microsoft/sp-loader");
var sp_lodash_subset_1 = require("@microsoft/sp-lodash-subset");
var ApplicationCustomizerContextFactory_1 = tslib_1.__importDefault(require("./ApplicationCustomizerContextFactory"));
var BaseApplicationCustomizer_1 = tslib_1.__importDefault(require("./BaseApplicationCustomizer"));
var ClientSideCustomAction_1 = tslib_1.__importDefault(require("./customAction/ClientSideCustomAction"));
var CustomActionLocations_1 = tslib_1.__importDefault(require("./customAction/CustomActionLocations"));
var PlaceholderManager_1 = tslib_1.__importDefault(require("./placeholder/PlaceholderManager"));
/**
 * A helper class for loading ApplicationCustomizer extensions.
 */
var ApplicationCustomizerLoader = /** @class */ (function () {
    function ApplicationCustomizerLoader(serviceScope) {
        var _this = this;
        this._customActionFromPreloadedData = [];
        this._debugCustomActions = [];
        this._debugCustomizerLoaded = false;
        sp_core_library_1.Validate.isNotNullOrUndefined(serviceScope, 'serviceScope');
        this._serviceScope = serviceScope;
        this._extensionManager = new sp_extension_base_1._ExtensionManager(this._serviceScope, BaseApplicationCustomizer_1.default);
        this._applicationCustomizerContextFactory = new ApplicationCustomizerContextFactory_1.default(this._serviceScope);
        // Initialize the placeholder manager.
        serviceScope.whenFinished(function () {
            _this._placeholderManager = serviceScope.consume(PlaceholderManager_1.default.serviceKey);
            _this._placeholderManager._enable();
        });
        this._currentCustomActions = new Set();
    }
    /**
     * This method is called when the client-side application is initializing and before it has
     * rendered. It loads the associated client-side extensions. It may perform asynchronous
     * operations.
     */
    ApplicationCustomizerLoader.prototype.loadExtensions = function (preloadedCustomActions) {
        var _this = this;
        var futureCustomActions = new Set(preloadedCustomActions);
        var hadCustomActions = this._currentCustomActions.size > 0;
        var hasDebugCustomActions = this._hasDebugCustomActions();
        // Will have custom actions include the debug ones to ensure those are always loaded
        var willHaveCustomActions = futureCustomActions.size > 0 || hasDebugCustomActions;
        var areCustomActionsEqual = (!hadCustomActions && !willHaveCustomActions) ||
            (hadCustomActions && willHaveCustomActions && sp_lodash_subset_1.isEqual(this._currentCustomActions, futureCustomActions));
        var extensionsDisposed = false;
        // If there were custom actions, dispose them before loading the new ones
        if (hadCustomActions && !areCustomActionsEqual) {
            sp_diagnostics_1._TraceLogger.logVerbose(ApplicationCustomizerLoader._logSource, 'Disposing existing extensions');
            this.disposeExtensions();
            extensionsDisposed = true;
        }
        this._currentCustomActions = futureCustomActions;
        if ((willHaveCustomActions && !areCustomActionsEqual) || // If new custom actions are needed, load them
            (hasDebugCustomActions && extensionsDisposed) // If we disposed debug extensions, make sure they are reloaded
        ) {
            sp_diagnostics_1._TraceLogger.logVerbose(ApplicationCustomizerLoader._logSource, 'Loading new extensions');
            return this._loadExtensions(preloadedCustomActions).then(function () { return _this._loadDebugCustomizerIfEnabled(); });
        }
        return this._loadDebugCustomizerIfEnabled();
    };
    /**
     * Disposes all existing application customizers and their associated placeholder contents.
     */
    ApplicationCustomizerLoader.prototype.disposeExtensions = function () {
        this._extensionManager.disposeExtensions();
        this._debugCustomizerLoaded = false;
        this._currentCustomActions.clear();
    };
    Object.defineProperty(ApplicationCustomizerLoader.prototype, "_customActions", {
        get: function () {
            return this._debugCustomActions.concat(this._customActionFromPreloadedData);
        },
        enumerable: false,
        configurable: true
    });
    /**
     * If the debugging flight is enabled, automatically add the debug application customizer.
     */
    ApplicationCustomizerLoader.prototype._loadDebugCustomizerIfEnabled = function () {
        var _this = this;
        var debugApplicationCustomizerId = 'd29758ba-0fc0-4eac-bcfd-7fe5a7d0bc32';
        if (sp_core_library_1._SPFlight.isDebugFlightEnabled &&
            sp_core_library_1._SPFlight.isEnabled(1178 /* SppplatDebugExtension */) &&
            !this._debugCustomizerLoaded &&
            this._isDebugModeOn(/* params */ undefined)) {
            var customAction_1 = ClientSideCustomAction_1.default._tryCreateFromDebugData('ClientSideExtension.ApplicationCustomizer', sp_core_library_1.Guid.parse(debugApplicationCustomizerId), // component id
            undefined, // properties,
            0 // Sequence
            );
            if (customAction_1) {
                this._debugCustomizerLoaded = true;
                return sp_loader_1._ManifestStore.instance
                    .requestManifest(debugApplicationCustomizerId)
                    .then(function () {
                    _this._createApplicationCustomizer(customAction_1);
                })
                    .catch(function (error) {
                    sp_diagnostics_1._TraceLogger.logError(ApplicationCustomizerLoader._logSource, error);
                });
            }
        }
        return Promise.resolve();
    };
    ApplicationCustomizerLoader.prototype._loadExtensions = function (preloadedCustomActions) {
        this._loadCustomActions(preloadedCustomActions);
        var extensionPromises = [];
        var customActions = this._customActions;
        for (var _i = 0, customActions_1 = customActions; _i < customActions_1.length; _i++) {
            var customAction = customActions_1[_i];
            if (customAction.location === CustomActionLocations_1.default.APPLICATION_CUSTOMIZER) {
                extensionPromises.push(this._createApplicationCustomizer(customAction));
            }
        }
        return Promise.all(extensionPromises).then(function (extensions) {
            return;
        });
    };
    ApplicationCustomizerLoader.prototype._createApplicationCustomizer = function (customAction) {
        var _this = this;
        var qosMonitor = new sp_diagnostics_1._QosMonitor('ApplicationCustomizer.Create');
        return this._extensionManager
            .createExtension(customAction.clientSideComponentId.toString(), customAction.clientSideComponentProperties, function (extensionContextParameters) {
            return _this._applicationCustomizerContextFactory.createApplicationCustomizerContext(customAction, extensionContextParameters, false);
        })
            .then(function (extension) {
            qosMonitor.writeSuccess(_this._createQosExtraData(customAction));
            return extension;
        })
            .catch(function (error) {
            var err = new Error("Failed to create application customizer '" + customAction.tag + "'. Error information is '" + error.message + "'.");
            qosMonitor.writeExpectedFailure('FailedCreateExtension', error, _this._createQosExtraData(customAction));
            sp_diagnostics_1._TraceLogger.logError(ApplicationCustomizerLoader._logSource, err);
            throw err;
        });
    };
    ApplicationCustomizerLoader.prototype._createQosExtraData = function (customAction) {
        return {
            customAction: customAction.tag
        };
    };
    /**
     * Loads custom actions from both the preloaded data and the query parameter.
     */
    ApplicationCustomizerLoader.prototype._loadCustomActions = function (customActions) {
        this._customActionFromPreloadedData = this._loadCustomActionsFromPreloadedData(customActions);
        this._debugCustomActions = this._loadCustomActionsFromQueryParameter();
    };
    /**
     * Reads the custom actions from the preloaded data and creates ClientSideCustomAction objects for them.
     * @param customActions - Custom actions from the preloaded data.
     * @returns Array with the processed custom actions.
     */
    ApplicationCustomizerLoader.prototype._loadCustomActionsFromPreloadedData = function (customActions) {
        var clientSideCustomActions = [];
        // There are scenarios when server side customActions object may not be present.
        // e.g., the client code gets shipped before the server code.
        // In this case we want to be tolerant and treat that as a condition with no
        // custom actions.
        if (!!customActions) {
            // Initialize all the custom actions.
            for (var _i = 0, customActions_2 = customActions; _i < customActions_2.length; _i++) {
                var customAction = customActions_2[_i];
                if (customAction.location === CustomActionLocations_1.default.APPLICATION_CUSTOMIZER) {
                    var clientSideCustomAction = ClientSideCustomAction_1.default._tryCreateFromPreloadedCustomAction(customAction);
                    // A failure to create the custom action will log an error and keep going.
                    if (clientSideCustomAction) {
                        clientSideCustomActions.push(clientSideCustomAction);
                    }
                }
            }
        }
        return clientSideCustomActions;
    };
    ApplicationCustomizerLoader.prototype._hasDebugCustomActions = function () {
        var queryParameters = new URL(window.location.href).searchParams;
        return (!!queryParameters.get('customActions') ||
            (sp_core_library_1._SPFlight.isDebugFlightEnabled &&
                sp_core_library_1._SPFlight.isEnabled(1178 /* SppplatDebugExtension */) && // for debug extension
                this._isDebugModeOn(queryParameters)));
    };
    ApplicationCustomizerLoader.prototype._isDebugModeOn = function (queryParameters) {
        if (!queryParameters) {
            queryParameters = new URL(window.location.href).searchParams;
        }
        if (sessionStorage.getItem('spfx-debug')) {
            // Don't load in TAB which monitor for unexpected files
            return !queryParameters.get('istabtest');
        }
        // Enable showing once ?debug is added as engineers typically do
        return !!queryParameters.get('debug');
    };
    ApplicationCustomizerLoader.prototype._loadCustomActionsFromQueryParameter = function () {
        // Example query parameter:
        // ?customActions={"e2d1da94-b7e9-4c57-9551-1e80a11a035b":{"location":"ClientSideExtension.
        //   ListViewCommandSet.ContextMenu","properties":{"message":"Hello"}}}
        //
        // Example deserialized JSON:
        // {
        //   "e2d1da94-b7e9-4c57-9551-1e80a11a035b": {                            // clientSideComponentId
        //     "location": "ClientSideExtension.ListViewCommandSet.ContextMenu",  // location
        //     "properties": { "message": "Hello" }                               // clientSideComponentProperties
        //    }
        // }
        var parameters = new URL(window.location.href).searchParams;
        var parameterValue = parameters.get('customActions');
        var clientSideCustomActions = [];
        if (parameterValue) {
            var qosMonitor = new sp_diagnostics_1._QosMonitor('ApplicationCustomizerLoader.parseQueryParam');
            try {
                var decodedParameterValue = decodeURIComponent(parameterValue);
                var queryValue = JSON.parse(decodedParameterValue);
                var missingManifestIds = [];
                if (queryValue) {
                    for (var _i = 0, _a = Object.keys(queryValue); _i < _a.length; _i++) {
                        var key = _a[_i];
                        var clientSideComponentId = sp_core_library_1.Guid.tryParse(key);
                        var location_1 = queryValue[key].location;
                        var properties = queryValue[key].properties;
                        var hostProperties = queryValue[key].hostProperties;
                        var sequence = queryValue[key].sequence;
                        sp_core_library_1.Validate.isNotNullOrUndefined(clientSideComponentId, 'clientSideComponentId');
                        sp_core_library_1.Validate.isNotNullOrUndefined(location_1, 'location');
                        if (!sp_loader_1.SPComponentLoader.tryGetManifestById(clientSideComponentId.toString())) {
                            missingManifestIds.push(clientSideComponentId);
                            continue; // Try to parse additional custom actions
                        }
                        if (clientSideComponentId && location_1) {
                            var customActions = ClientSideCustomAction_1.default._tryCreateFromDebugData(location_1, clientSideComponentId, properties ? JSON.stringify(properties) : '', sequence, hostProperties ? JSON.stringify(hostProperties) : '');
                            if (customActions) {
                                clientSideCustomActions.push(customActions);
                            }
                        }
                    }
                }
                if (missingManifestIds.length > 0) {
                    this._processMissingManifestsErrors(missingManifestIds, qosMonitor);
                }
                else {
                    qosMonitor.writeSuccess();
                }
            }
            catch (e) {
                this._processQueryParamParseErrors(e, parameterValue, qosMonitor);
            }
        }
        return clientSideCustomActions;
    };
    ApplicationCustomizerLoader.prototype._processMissingManifestsErrors = function (missingManifestIds, qosMonitor) {
        var errorMessage = 'Custom action component ids are specified by query parameters but ' +
            'matching manifests cannot be found.';
        var error = new Error(errorMessage + ' Ids: ' + missingManifestIds.join(', '));
        sp_diagnostics_1._TraceLogger.logError(ApplicationCustomizerLoader._logSource, error, 'parseCustomActionsQueryParameter');
        // NOTE: Normally SPFx code does not use console.error(), but in this scenario we are
        // talking directly to a developer.  They really need to see this string without the
        // truncating/scrubbing that is normally performed by the Dev Dashboard "Trace" tab.
        console.error(error.message);
        qosMonitor.writeExpectedFailure('ManifestNotFound', error);
    };
    ApplicationCustomizerLoader.prototype._processQueryParamParseErrors = function (error, parameterValue, qosMonitor) {
        sp_diagnostics_1._TraceLogger.logError(ApplicationCustomizerLoader._logSource, new Error('Failed to parse the "customActions" URL query parameter:' + error.message));
        // NOTE: Normally SPFx code does not use console.error(), but in this scenario we are
        // talking directly to a developer.  They really need to see this string without the
        // truncating/scrubbing that is normally performed by the Dev Dashboard "Trace" tab.
        console.error('The "customActions" URL query parameter is improperly formatted: ' + decodeURIComponent(parameterValue));
        qosMonitor.writeExpectedFailure('ParseFailure', error);
    };
    ApplicationCustomizerLoader._logSource = sp_diagnostics_1._LogSource.create('ApplicationCustomizerLoader');
    return ApplicationCustomizerLoader;
}());
exports.default = ApplicationCustomizerLoader;
//# sourceMappingURL=ApplicationCustomizerLoader.js.map