// Global vars
var g_eid;
var g_sid;
var g_rid;
var g_userArr;
var g_httprequest;
var g_pollTimer;
var g_curPollingInterval = MIN_POLL_INTERVAL;
var g_exitRegistered = false;
var g_refreshImgCounter = 0;
var g_msgCache = "";
var g_divCache = new Array();
var g_divBuffer = new Array(); // Array of div caches
// Remember last jquery object holding the server response so that we can
// append new server responses immediately after it.
var g_lastInsertedElement = null;
var g_myColor;
var g_myName;

function openEmbedWindow(){
	window.open("/embedcode?rid="+window.g_rid, "embedcode", "width=630,height=400");
}

function scrollDown() {
	// Bump scrolling div down
	elem = document.getElementById("chatArea");
  elem.scrollTop = elem.scrollHeight;
}

/**
 * This function is attached to the onload event of <img> tags to limit the width of the
 * image to EMBED_IMAGE_WIDTH.
 * @param {HTMLElement} img The image to resize.
 */
function adjustImage(img) {
	width = img.width;
	if (width>EMBED_IMAGE_WIDTH) {
		img.width = EMBED_IMAGE_WIDTH;
	}
}

/**
 * Renders the div containing the list of users in the chat room. Each user's name
 * is a link that will trigger a private conversation invite to the user when it is
 * clicked on.
 */
function updateUserList() {
  	userListHTML = "";
  	for (var i=0; i<window.g_userArr.length; i++) {
		// Generate the username link -- this applies to both logged in and non-logged in users.
  		usernameText = "<span style='color: "+window.g_userArr[i][1]+"'><span ";
		if (window.g_userArr[i][2]!=window.g_sid) {
			// Don't hyperlink the user's own name
			usernameText += "onclick=\"openPrivateChat("+window.g_rid+", '"+window.g_userArr[i][2]+"')\" "; 
			usernameText += "title=\"Click to request private chat with user\" ";
			usernameText += 'class="usernameWithLink" ';
		} else {
			usernameText += 'class="usernameNoLink" ';
			usernameText += "title=\"That's you!\" ";
			// Populate some globals with info on how to render the user's name
			window.g_myColor = window.g_userArr[i][1];
			window.g_myName = window.g_userArr[i][0];	
		}
		usernameText += ">"+window.g_userArr[i][0]+"</span></span><br/>";

		if (window.g_userArr[i][3]) {
			// User is logged in
			imgUrl = "/img?sid=" + window.g_userArr[i][2];
			imgUrl += "&z=" + window.g_refreshImgCounter;
			oneUser = "<div class='profileContainer'><img width='28' height='28' src='"+imgUrl+"'/>";
			oneUser += "<div class='profileText'>";
  			oneUser += usernameText;
			oneUser += "<span class='user_status'>" + window.g_userArr[i][4] + "</span><br/>";
			oneUser += "</div></div>";
		} else {
			// User is not logged in. Just render the username link.
			oneUser = "<div class='profileContainerNotLoggedIn'>"+usernameText+"</div>";
		}
		userListHTML += oneUser;
  	}
  	$("#userList").html(userListHTML);
}

/**
 * Opens a private chat window when a user initiates a private chat.
 * @param {int} rid The current chat room's room ID.
 * @param {string} callee The key value of the user that is receiving the chat invite.
 */
function openPrivateChat(rid, callee){
	var date = new Date();	
	var url = "/private?rid=" + rid + "&c=" + callee + "&z=" + date.getTime();
	// Name the window in such a way to prevent duplicate windows
	window.open(url, window.g_sid+callee+rid, "resizable,titlebar,toolbar,scrollbars,height="+ROOM_HEIGHT+",width="+ROOM_WIDTH);
}

/**
 * Opens a private chat window when a user accepts a private chat invite.
 * @param {int} rid The room ID of the private chat room.
 */
function acceptPrivateChat(rid){
	var date = new Date();
	var adTargetingString = encodeURIComponent($("#roomName").html() + " " + $("#tags").html());
	var url = "/chatroom?rid=" + rid + "&n=" + adTargetingString;
	// Name the window in such a way to prevent duplicate windows
	window.open(url, "yt"+rid, "resizable,titlebar,toolbar,scrollbars,height="+ROOM_HEIGHT+",width="+ROOM_WIDTH);
}


/**
 * Updates the chat window (chat text and user list). If the room hasn't changed since the last
 * ping, increase the time to wait before pinging the server for an update.
 * @param {object} chatObj Contains up to date info about the chat messages and users in the room.
 */
function updateChatWindow(chatObj) {

	removeList = window.g_divBuffer.shift();
	for (d=0; d<removeList.length; d++) {
		removeList[d].remove();
	}

	if (chatObj.newEid <= window.g_eid) {
		window.g_curPollingInterval += POLL_INTERVAL_STEP;
		if (window.g_curPollingInterval > MAX_POLL_INTERVAL) {
			window.g_curPollingInterval = MAX_POLL_INTERVAL;
		}
		return;
	}
	window.g_eid = chatObj.newEid;

	// There is room activity. Reset polling interval to min value.
	window.g_curPollingInterval = MIN_POLL_INTERVAL;

	if (chatObj.refreshImg) {
		// Profile images have changed. Increment the cache buster value to force browser
		// to refetch all profile images.
		window.g_refreshImgCounter++;
	}
	
	newElement = $('<div>'+chatObj.chatTxt+'</div>');
	if (window.g_lastInsertedElement) {
		window.g_lastInsertedElement.after(newElement);
	} else {
		// This is the first response on the page.
		$("#chatArea").append(newElement);
	}
	window.g_lastInsertedElement = newElement;
	scrollDown();

	window.g_userArr = chatObj.userArr;
	if (chatObj.userArr.length > 0) {
		updateUserList();
	}
	  
  	// Disable text entry and submit if the response code is not 0
	if (chatObj.respCode != 0) {
		$("#userInput").disabled = true;
		$("#submit").disabled = true;
		window.g_exitRegistered = true; // Prevents user from getting removed again
	} 
  
}

/**
 * Sends off an HTTP request when the user enters a chat message.
 */
function sendChat() {
	// Ignore if the user didn't type anything
	if ($("#userInput").val()=="") {
		return
	}
	// Send chat message when the next polling message goes out.
	if (window.g_msgCache != "") {
		window.g_msgCache += '\n';
	}
	window.g_msgCache += $("#userInput").val();
	// We give the illusion of responsiveness by immediately writing
	// the user's input to the screen. Once we receive a response from the
	// server, the pre-processed client text is deleted from the DOM and replaced
	// with the actual response from the server.
	newDiv = $('<div class="chatText"><span style="color: '+window.g_myColor+'" class="userNameInChat">'
						 +window.g_myName+':</span> '
						 +$("#userInput").val()+'</div>');
	
	window.g_divCache.push(newDiv);
	$("#chatArea").append(newDiv);	
	scrollDown();
	$("#userInput").val("");
}

/**
 * This function is repeatedly called in the background to poll the server for updates.
 */
function sendPoll(){
	// Make a note of prewritten divs written so far. This set will be deleted once
	// the ajax call returns.
	window.g_divBuffer.push(window.g_divCache);
	window.g_divCache = new Array();
	
	window.g_httprequest = XMLRequest();
  	if (window.g_httprequest) {  
		window.g_httprequest.onreadystatechange = handlePollResponse;
    	window.g_httprequest.open("GET", "/chat?" + makeChatRequest(), true);
    	window.g_httprequest.send("");
	} else {
		// In the unlikely event that XMLRequest fails, we'll need to retry. 
		// Background polling must not be allowed to stop.
		setTimeout(sendPoll, 2000);
	}
}

/**
 * Helper function to handle the response obtained as a result of calling sendPoll().
 */
function handlePollResponse() {
	if (window.g_httprequest.readyState == 4) {
		try {
			if (window.g_httprequest.status == 200) {
				resp = window.g_httprequest.responseText;
				var func = new Function("return " + resp);
				var chatObj = func();
				updateChatWindow(chatObj); 
				if (chatObj.respCode == 0) {
					window.g_pollTimer = setTimeout(sendPoll, window.g_curPollingInterval);
				} 
			} else {
				// Continue polling anyway
				window.g_pollTimer = setTimeout(sendPoll, window.g_curPollingInterval);
			}
		} catch (e) {
			// Resume background polling nevertheless.
			window.g_pollTimer = setTimeout(sendPoll, window.g_curPollingInterval);
		}		  
	}
}

/**
 * Sends a synchronous HTTP request to register an exit. 
 * Added to both onunload and onbeforeunload to maximize browser compatibility.
 * Note that XMLRequest() fails in IE when called from onunload.
 */
function exitRoom() {
	if (!window.g_exitRegistered) {
		// Clear poll
  		clearTimeout(window.g_pollTimer);
		window.g_httprequest.abort();
		var date = new Date();
		var request = XMLRequest();
		if (request) {  
			var date = new Date();	
			request.open("GET", "/exit?sid="+window.g_sid+"&rid="+window.g_rid+"&z="+date.getTime(), false);
			request.send("");
			window.g_exitRegistered = true;
  		}
	}
}

/**
 * Helper function that assembles the HTTP request URL for calling the server to update the chat page.
 * @param {boolean} polling True if this is a poll (vs a request sent when the user sends a chat message).
 */
function makeChatRequest() {
  msg = encodeURIComponent(window.g_msgCache);
	window.g_msgCache = "";
  var date = new Date(); 
  getStr = "m=" + msg +
           "&rid=" + window.g_rid +
           "&eid=" + window.g_eid +
           "&z=" + date.getTime();
  return getStr;
}
