"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const pluginSlice_1 = require("../../store/pluginSlice");
const config_1 = __importDefault(require("../../utils/config"));
class PluginManager {
    constructor(socketObj, roomName, dispatch, peerId, authToken) {
        this.socketObj = socketObj;
        this.dispatch = dispatch;
        this.roomName = roomName;
        this.plugins = {};
        this.iframes = {};
        this.peerId = peerId;
        this.authToken = authToken;
        this.handleSockets = this.handleSockets.bind(this);
    }
    handleSockets(message) {
        if (!message) {
            return;
        }
        switch (message.type) {
            case 'websocket/enable-plugin':
                this.enablePlugin(message.payload);
                break;
            case 'websocket/disable-plugin':
                this.disablePlugin(message.payload);
                break;
            case 'websocket/plugin-event':
            case 'websocket/plugin-data':
                this.sendIframeEvent(message);
                break;
            default:
                break;
        }
    }
    sendIframeEvent(message) {
        const views = this.iframes[message.payload.pluginId || message.payload.id];
        if (views) {
            Object.values(views).forEach((view) => {
                if (view.iframe) {
                    view.iframe.injectJavaScript(`window.postMessage(${JSON.stringify(message)});`);
                }
            });
        }
    }
    listenSocketEvents() {
        this.socketObj.emitter.on('socket', this.handleSockets);
        this.getRoomPlugins();
    }
    getRoomPlugins() {
        this.socketObj.sendMessage({ type: 'getRoomState' }, (message) => {
            const roomPlugins = message.payload.roomState.plugins;
            roomPlugins.forEach((p) => this.enablePlugin(p));
        });
    }
    enablePlugin(plugin) {
        return __awaiter(this, void 0, void 0, function* () {
            const pluginBase = `${config_1.default.apiBase}/v2/plugins`;
            if (this.plugins[plugin.id]) {
                return;
            }
            const pluginReq = yield fetch(`${config_1.default.apiBase}/v2/plugins/view/${plugin.id}`, {
                method: 'GET',
                headers: {
                    authorization: `Bearer ${this.authToken}`,
                },
            });
            const pluginDetails = yield pluginReq.json();
            const authTokenReq = yield fetch(`${pluginBase}/authorize/${plugin.id}`, {
                method: 'POST',
                headers: {
                    authorization: `Bearer ${this.authToken}`,
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    roomName: this.roomName,
                    peerId: this.peerId,
                }),
            });
            const authToken = (yield authTokenReq.json()).data.token;
            const newPlugin = Object.assign(Object.assign({}, pluginDetails.data.plugin), { authToken, enabledBy: plugin.enabledBy, ACLAccessGrantedUsers: plugin.ACLAccessGrantedUsers || [], ACLAccessRemovedUsers: plugin.ACLAccessRemovedUsers || [] });
            this.plugins[plugin.id] = newPlugin;
            this.iframes[plugin.id] = {};
            this.dispatch(pluginSlice_1.addPlugin(newPlugin));
        });
    }
    disablePlugin(plugin) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.plugins[plugin.id]) {
                delete this.plugins[plugin.id];
                this.dispatch(pluginSlice_1.removePlugin(plugin));
            }
        });
    }
    handleIframeMessage(message) {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            switch (message.type) {
                case 'pluginEvent':
                case 'storePluginData':
                case 'getPluginData':
                case 'enablePluginForAll':
                    this.socketObj.sendMessage(message, (resp) => {
                        this.sendIframeEvent(resp);
                    });
                    break;
                case 'getPeerInfo': {
                    this.socketObj.sendMessage({
                        type: message.type,
                        payload: Object.assign(Object.assign({}, message.payload), { peerId: (_b = (_a = message.payload) === null || _a === void 0 ? void 0 : _a.peerId) !== null && _b !== void 0 ? _b : this.peerId }),
                    }, (resp) => {
                        this.sendIframeEvent(resp);
                    });
                    break;
                }
                default:
                    break;
            }
        });
    }
    addIframeView(frame, element, EM) {
        return __awaiter(this, void 0, void 0, function* () {
            // If view already existed, cleanup the previous event listeners
            if (this.iframes[frame.plugin][frame.view]) {
                this.removeIframeView(frame);
            }
            const listener = (message) => {
                if (!element) {
                    return;
                }
                this.handleIframeMessage(message);
            };
            EM.addEventListener(listener);
            this.iframes[frame.plugin][frame.view] = {
                listener,
                iframe: element,
            };
        });
    }
    removeIframeView(frame) {
        return __awaiter(this, void 0, void 0, function* () {
            const view = this.iframes[frame.plugin][frame.view];
            if (view) {
                // window.removeEventListener('message', view.listener);
                delete this.iframes[frame.plugin][frame.view];
            }
        });
    }
    addRoomPlugin(plugin) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.plugins[plugin.id]) {
                return;
            }
            yield this.socketObj.sendMessage({
                type: 'addPlugin',
                payload: plugin,
            });
        });
    }
    removeRoomPlugin(plugin) {
        return __awaiter(this, void 0, void 0, function* () {
            return this.socketObj.sendMessage({
                type: 'removePlugin',
                payload: plugin,
            });
        });
    }
}
exports.default = PluginManager;
//# sourceMappingURL=PluginManager.js.map