(function () {
	
	function isServedByEspresso(url) {
		if (!url) return false;
		return url.indexOf("localhost:") !== -1;
	}
	
	(function() {
		function EspressoLiveSocket() {
			
			var _socket = new WebSocket("ws://" + document.location.host + "/__EspressoLive__");
			var _socketMessageQueue = [];
	 
			window.__EspressoLive__msgSend = function(message) {
				
				// Queue messages if the socket isn't open yet
				if (_socket.readyState == 0) {
					_socketMessageQueue.push(message);
				}
				else {
					try {
	 					// Make sure nobody messes with the expected format
						if ('toJSON' in Array.prototype) {
	 						var overriddenToJSON = Array.prototype.toJSON;
							delete Array.prototype.toJSON;
						}
						
						var messageString = JSON.stringify(message);
						
						if (overriddenToJSON) {
							Array.prototype.toJSON = overriddenToJSON;
						}
						
						_socket.send("msg:"+messageString);
					} catch (error) { console.log("__EspressoLive__msgSend error: " + error + "; message: " + JSON.stringify(message)); }
				}
			};
			
			_socket.onopen = function() {
	 
				// Send any messages that were queued up before the socket opened
				for (var i = 0; i < _socketMessageQueue.length; i++) {
					window.__EspressoLive__msgSend(_socketMessageQueue[i]);
				}
				_socketMessageQueue = [];
			};
			
			_socket.onmessage = function(event) {
				var packet = JSON.parse(event.data);
				if (packet.type === "ejs") {
					var script = packet.js;
					var result = eval(script);
					if (packet.ret !== undefined) {
						_socket.send("ret:"+packet.ret+":"+JSON.stringify([result]));
					}
					return;
				}
				else {
					console.log("EspressoLiveSocket received unknown message: " + message);
				}
			};
		}
		
		if (!window.WebSocket || !isServedByEspresso(document.location.host) || ((typeof window.__EspressoLiveIsInAppPreview__ !== "undefined" && window.__EspressoLiveIsInAppPreview__))) {
			return null;
		}
		else {
			return (new EspressoLiveSocket());
		}
	})();
	
	
	(function()
	{
		// Help the server distinguish AJAX requests so the script isn't injected in responses
		
		XMLHttpRequest.prototype.__requestHeaders__ = {};
		XMLHttpRequest.prototype._getRequestHeader = function(headerName)
		{
			return this.__requestHeaders__[headerName];
		}
		
		var setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
		XMLHttpRequest.prototype.setRequestHeader = function(headerName, headerValue)
		{
			this.__requestHeaders__[headerName] = headerValue;
			setRequestHeader.apply(this, arguments);
		}
		
		var open = XMLHttpRequest.prototype.open;
		XMLHttpRequest.prototype.open = function(method, url, etc)
		{
			this.__url__ = url;
			open.apply(this, arguments);
		}
					
		var send = XMLHttpRequest.prototype.send;
		XMLHttpRequest.prototype.send = function(data)
		{
			if (isServedByEspresso(this.__url__) && this._getRequestHeader("X-Requested-With") === undefined) {
				console.log("patched", this.__url__);
				this.setRequestHeader("X-Requested-With", "XMLHttpRequest");
			}
			
			send.apply(this, arguments);
		}
	})();
})();
