/* requires jQuery, Mediasite.Player.WindowInterface */

window.Mediasite = window.Mediasite || {};
Mediasite.Player = Mediasite.Player || {};


Mediasite.Player.WindowMessageBroker = function(thisWindowInterface, externalWindowInterface) {
	var messages = [];
	function logMessage(message, direction) {
		message = $.extend({}, message, { direction: direction });
		messages.push(message);
	}

	var broker = this;
	var handlers = {};
	var callbacks = [];
	var destroyed = false;


	broker.setHandler = function(type, callback) {
		handlers[type] = callback;
	};
	broker.destroy = function() {
		thisWindowInterface.removeHandler('message', receiveMessageEvent);
		destroyed = true;
	};
	broker.logMessages = function() {
		// For diagnostic purposes only
		if (window.console) {
			if (console.table) { 
				console.table(messages);
			} else {
				for (var i = 0, length = messages.length; i < length; i++) {
					var message = JSON.stringify(messages[i]);
					console.log(message);
				}
			}
		}
	}

	broker.sendMessage = sendMessage;

	thisWindowInterface.addHandler('message', receiveMessageEvent);

	function receiveMessageEvent(event) {
		var data = event.data;
		var source = event.source;

		if (!externalWindowInterface.equals(source)) { 
			return; 
		}

		var message = parseMessageData(data);

		if (message) {
			var handled = callCallback(message);
			if (handled === false) {
				handled = callHandler(message);
			}
		}

		logMessage(message, "received");

	}


	function parseMessageData(encodedData) {
		var message;
		try {
			message = JSON.parse(encodedData);
		} catch (e) {
			// message probably isn't intended for me
		}

		return message;
	}

	function callCallback(message) {
		if (message.type !== '_callback' || message.callbackId === void 0) {
			return false;
		}

		var callback = callbacks[message.callbackId];
		if (!callback) {
			return false;
		} else {
			callback(message.data);
			return true;
		}
	}

	function callHandler(message) {
		var callback = handlers[message.type];
		if (!callback) {
			return false;
		} else {
			callback(message.data, respond.bind(broker, message));
			return true;
		}
	}

	function respond(message, responseData) {
		if (message.callbackId !== void 0) {
			var responseMessage = {
				type: '_callback',
				data: responseData,
				callbackId: message.callbackId
			}
			postMessage(responseMessage);
		}
	}

	function sendMessage (type, data, callback) {
		var callbackId;
		if (callback) {
			callbacks.push(callback);
			callbackId = callbacks.length - 1;
		}

		var message = {
			type: type,
			data: data,
			callbackId: callbackId
		};

		postMessage(message);
	};

	function postMessage(message) {
		if (destroyed) { return; }
		
		var messageData = JSON.stringify(message);
		logMessage(message, "send");
		externalWindowInterface.postMessage(messageData, "*");
	}
	
	return broker;
};

Mediasite.Player.WindowMessageBroker.fromMainWindowToPopout = function(popoutWindow) {
	var thisWindowInterface;
	var externalWindowInterface;
	var ie = Mediasite.BrowserDetect.InternetExplorer();

    if (ie && ie == 11) {
		thisWindowInterface = $.extend({}, new Mediasite.Player.WindowInterface(window), new Mediasite.Player.WindowInterfaceIE11Popout());
		externalWindowInterface = $.extend({}, new Mediasite.Player.WindowInterface(popoutWindow), new Mediasite.Player.WindowInterfaceIE11Popout());
    } else {
		thisWindowInterface = new Mediasite.Player.WindowInterface(window);
		externalWindowInterface = new Mediasite.Player.WindowInterface(popoutWindow);
	}
	
	var broker = new Mediasite.Player.WindowMessageBroker(thisWindowInterface, externalWindowInterface);

	return broker;
};

Mediasite.Player.WindowMessageBroker.fromPopoutToMainWindow = function() {
	var thisWindowInterface;
	var mainWindowInterface;
	var ie = Mediasite.BrowserDetect.InternetExplorer();

    if (ie && ie == 11) {
		thisWindowInterface = $.extend({}, new Mediasite.Player.WindowInterface(window), new Mediasite.Player.WindowInterfaceIE11Popout());
		mainWindowInterface = $.extend({}, new Mediasite.Player.WindowInterface(window.opener), new Mediasite.Player.WindowInterfaceIE11Popout());
    } else {
		thisWindowInterface = new Mediasite.Player.WindowInterface(window);
		mainWindowInterface = new Mediasite.Player.WindowInterface(window.opener);
	}

	var broker = new Mediasite.Player.WindowMessageBroker(thisWindowInterface, mainWindowInterface);

	return broker;
};


// Provides a base strategy for WindowMessageBroker.
// This strategy pattern is employed to provide a default no-op behavior in cases when an exception has occured when trying to instantiate a WindowMessageBroker module.
// See BUG43376: 	Player: Stream pop-outs from multiview don't work in Edge browser
// Mediasite.Player.SmartPlayerView.StandaloneStreamInspectorLauncher.launch() in SmartPlayer/PlayerView.js

Mediasite.Player.WindowMessageBrokerBase = function () {
    this.setHandler = function() { };
    this.destroy = function() { };
    this.logMessages = function() { };
    this.sendMessage = function() { };
}
