import { Injectable } from '@angular/core';

import {
	ContextService,
	HttpService,
	PanelService,
	PanelType,
	OpenViduService,
	LoggerService
} from 'projects/shared-meet-components/src/public-api';
import { WebComponentCommand } from 'webcomponent/src/models/command.model';
import { OutboundEventMessage, InboundCommandMessage } from 'webcomponent/src/models/message.type';

/**
 * Service to manage the commands from OpenVidu Meet WebComponent/Iframe.
 * This service listens for messages from the iframe and processes them.
 * It also sends messages to the iframe.
 */
@Injectable({
	providedIn: 'root'
})
export class WebComponentManagerService {
	protected isListenerStarted = false;
	protected log;

	constructor(
		protected loggerService: LoggerService,
		protected contextService: ContextService,
		protected panelService: PanelService,
		protected openviduService: OpenViduService,
		protected httpService: HttpService
	) {
		this.log = this.loggerService.get('OpenVidu Meet - WebComponentManagerService');
	}

	startCommandsListener(): void {
		if (this.isListenerStarted) return;

		this.isListenerStarted = true;
		// Listen for messages from the iframe
		window.addEventListener('message', async (event) => {
			const message: InboundCommandMessage = event.data;
			const parentDomain = this.contextService.getParentDomain();
			const { command, payload } = message;

			if (!parentDomain) {
				if (command === WebComponentCommand.INITIALIZE) {
					if (!payload || !('domain' in payload)) {
						console.error('Parent domain not provided in message payload');
						return;
					}
					this.log.d(`Parent domain set: ${event.origin}`);
					this.contextService.setParentDomain(payload['domain']);
				}
				return;
			}

			if (event.origin !== parentDomain) {
				// console.warn(`Untrusted origin: ${event.origin}`);
				return;
			}

			console.debug('Message received from parent:', event.data);
			// TODO: reject if room is not connected
			switch (command) {
				case WebComponentCommand.END_MEETING:
					// Moderator only
					if (this.contextService.isModeratorParticipant()) {
						const roomId = this.contextService.getRoomId();
						await this.httpService.endMeeting(roomId);
					}
					break;
				// case WebComponentCommand.TOGGLE_CHAT:
				// Toggle chat
				// this.panelService.togglePanel(PanelType.CHAT);
				// break;
				case WebComponentCommand.LEAVE_ROOM:
					// Leave room.
					await this.openviduService.disconnectRoom();
					break;
				default:
					break;
			}
		});
	}

	stopCommandsListener(): void {
		if (!this.isListenerStarted) return;
		this.isListenerStarted = false;
		window.removeEventListener('message', this.startCommandsListener);
	}

	sendMessageToParent(event: OutboundEventMessage) {
		if (!this.contextService.isEmbeddedMode()) return;
		this.log.d('Sending message to parent :', event);
		const origin = this.contextService.getParentDomain();
		window.parent.postMessage(event, origin);
	}
}
