/*!
 * Copyright (C) Microsoft Corporation. All rights reserved.
 */
/** @private */
export class DefaultPowerAppsBridge {
    _antiCSRFToken;
    _callbacks = {};
    _currentCallbackId = 0;
    _instanceId = Date.now().toString();
    _messageChannel = new window.MessageChannel();
    _postMessageQueue = [];
    _postMessageSource;
    async initialize() {
        this._messageChannel.port1.onmessage = this._handleMessageEvent;
        window.parent.postMessage({
            messageType: 'initCommunicationWithPort',
            instanceId: this._instanceId,
        }, '*', [this._messageChannel.port2]);
    }
    async executePluginAsync(pluginName, pluginAction, params = [], onUpdate) {
        return new Promise((resolve, reject) => {
            const callbackId = this._getCallbackId(pluginName);
            this._callbacks[callbackId] = { resolve, reject, onUpdate };
            this._sendMessage({
                isPluginCall: true,
                callbackId,
                service: pluginName,
                action: pluginAction,
                actionArgs: params,
                antiCSRFToken: this._antiCSRFToken,
            });
        });
    }
    _sendMessage(message) {
        if (!this._postMessageSource) {
            this._postMessageQueue.push(message);
        }
        else {
            this._postMessageSource.postMessage(message);
        }
    }
    _getCallbackId(pluginName) {
        return 'instanceId=' + this._instanceId + '_' + pluginName + this._currentCallbackId++;
    }
    _handleMessageEvent = (messageEvent) => {
        const message = messageEvent.data;
        // Capture only the messages that are sent via the App Host's CommunicationChannel
        // which always provides an isPluginCall boolean value.
        if (message && typeof message.isPluginCall === 'boolean') {
            // message can be either a native plugin call result, or a script to execute
            if (message.isPluginCall) {
                // this is the result of a plugin call, extract the parameters and return them
                const callbackId = message.callbackId;
                const status = message.status;
                const args = message.args;
                const keepCallback = message.keepCallback;
                try {
                    const callback = this._callbacks[callbackId];
                    if (keepCallback) {
                        if (callback && callback.onUpdate) {
                            callback.onUpdate(message.args?.[0]);
                        }
                    }
                    else {
                        if (callback) {
                            if (status === 1) {
                                callback.resolve(args[0]);
                            }
                            else if (status !== 0) {
                                callback.reject(args);
                            }
                        }
                        if (!keepCallback) {
                            delete this._callbacks[callbackId];
                        }
                    }
                }
                catch (error) {
                    // eslint-disable-next-line no-console
                    console.error(error);
                }
            }
        }
        else if (message && message.messageType === 'initCommunication') {
            this._antiCSRFToken = message.antiCSRFToken;
            this._postMessageSource = this._messageChannel.port1;
            if (this._postMessageSource) {
                for (let i = 0; i < this._postMessageQueue.length; i++) {
                    // backfill csrf token
                    this._postMessageQueue[i].antiCSRFToken = this._antiCSRFToken;
                    this._postMessageSource.postMessage(this._postMessageQueue[i]);
                }
            }
        }
    };
}
//# sourceMappingURL=DefaultPowerAppsBridge.js.map