/**
 * @fileoverview Utility javascript used in the online games service
 */

//global variables
var communityBaseurl = contextPath + "discovery/";
var htmlIDsToUpdateWithCounts = new Array(); //a global javascript array which will be populated with HTML IDs
var gameIDsToCount = new Array(); //a global javascript array which will be populated with gameids
var OVERALLGAMECOUNTID = 'community';
var BATCHSIZEFORGAMECOUNTS = 20;
var TIMEOUTSECONDS = 20;
var IFRAME_INIT = new Array();
IFRAME_INIT['registrationIframe'] = {'src': securePath + 'basicRegister.jsf?_flowId=registration-flow&ts=' + returnTimeStampString(),
			'height': 0,
			'width': 740,
			'headerImg': staticFileBase + 'images/overlayheader_740x37.png',
			'footerImg': staticFileBase + 'images/overlayfooter_740x17.png'};
IFRAME_INIT['signinIframe'] = {'src': securePath + 'basicLogin.jsf?ts=' + returnTimeStampString(),
			'height': 250,
			'width': 500,
			'headerImg': staticFileBase + 'images/overlayheader_500x37.png',
			'footerImg': staticFileBase + 'images/overlayfooter_500x17.png'};

// fix for array indexof
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:indexOf#Compatibility
if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(elt /*, from*/) {
		var len = this.length;
		var from = Number(arguments[1]) || 0;
		from = (from < 0)
				? Math.ceil(from)
				: Math.floor(from);
		if (from < 0) from += len;
		for (; from < len; from++) {
			if (from in this && this[from] === elt) return from;
		}
		return -1;
	};
}

/**
 * @return {String} a timestamp string
 */
function returnTimeStampString() {
	var timeStamp = new Date();
	return timeStamp.getTime();
}

/**
 * Sets the content of an HTML element
 * @param {String} element is the id of the element whose content you want to set
 * @param {String} content is the content you want to set inside the element
 * @return null
 */
function setInnerHTML(element,content) {
	document.getElementById(element).innerHTML = content;
}

/**
 * Toggles an element's disabled property to true, i.e., disables an element
 * @param {String} element is the id of the element to disable
 * @return null
 */
function disableElement(element) {
	document.getElementById(element).disabled = true;
}

/**
 * Toggles an element's disabled property to false, i.e., enables an element
 * @param {String} element is the id of the element to enable
 * @return null
 */
function enableElement(element) {
	document.getElementById(element).disabled = false;
}

/**
 * TODO
 */
function setDisplayError(element,msg) {
	setInnerHTML(element,msg);
	dojo.html.show(document.getElementById(element));
}

/**
 * a function which takes a comma-delimited list of gameids (usually the gameIDsToCount 
 * global string) as an argument, makes an asynchronous GET request, waits for counts to be 
 * returned keyed by gameid in a JSON format, and then calls a response handler renderGameCountDivs
 * @param {String} gameIds a comma-delimited list of gameids
 */ 
function getGameCounts(gameIds) {
 	var params = new Array();
 	params['gameId'] = gameIds;
 	params['ts'] = returnTimeStampString();
 	var bindArgs = {
  		url: returnCorrectprotocolURL(communityBaseurl + "getGameUserCount.json"),
  		error: function(type, data, evt) {
    		renderGameCountDivs(0, gameIds);
   	 	},
   	 	load: function(type, data, evt) {
   	 		renderGameCountDivs(data, gameIds);
   	 	},
  		mimetype: "text/json",
  		timeoutSeconds: TIMEOUTSECONDS,
		timeout: function(type, data, evt){
			renderGameCountDivs(0, gameIds);
		},
		content: params
 	};
 	var req = dojo.io.bind(bindArgs);
}

/**
 * a response handler function which loops through the global array of HTML IDs htmlIDsToUpdateWithCounts. 
 * For each ID it obtains a handle on the HTML element, uses REGEX to obtain the actual gameid from 
 * the current ID, uses that gameid to retrieve the count from the returned JSON, and then updates 
 * the DOM with that count using innerHTML.
 * @param {Array} gameIds is an array containing game IDs
 * @param {Object} data is a JSON object returned by the backend
 */
function renderGameCountDivs(data, gameIds) {
	if (htmlIDsToUpdateWithCounts) {
	  	//ensure that we are dealing with a string first, and then put it into an array
  		var gameIds = gameIds.toString();
  		gameIds = gameIds.split(',');
 		//loop over the array
 		for (var i=0; i < gameIds.length; i++) {
 			//grab the current game
 			var currentGame = gameIds[i];
 			if (currentGame != '') {
 				//find out its index in the global arrays
 				var indexOfGameId = gameIDsToCount.indexOf(currentGame);
 				//once we know its index, replace the data with a blank string
 				//this handles the case where the same game appears on the same page more than once
 				if (indexOfGameId != -1) {
 					gameIDsToCount.splice(indexOfGameId,1,"");
 				}
	  			//get the corresponding HTML ID
	  			var htmlID = htmlIDsToUpdateWithCounts[indexOfGameId + currentGame] ;
			  	//get handle on DOM
			  	var elementToUpdate = document.getElementById(htmlID);
	  			//update the DOM
	  			if (data != 0 && elementToUpdate) {
	  				elementToUpdate.innerHTML = data.onLineGameCountMap[currentGame];
  				} else {
  					// if data = 0 then we know that the XMLHttpRequest timed out
  					var unavailableNode = document.createElement('span');
  					unavailableNode.className = 'px10';
  					unavailableNode.innerHTML = unavailable;
  					elementToUpdate.appendChild(unavailableNode);
			  	}
 			}
  		}
	}
}

/**
* a function which runs on page load, parses the current page for HTML elements (currently 
* configured to look for span and div) with the class gamecount. It populates the global array, 
* htmlIDsToUpdateWithCounts, from the id attributes, and using REGEX it populates the global array, 
* gameIDsToCount with gameids. The fact that these two arrays are populated in synch is significant.
*
*/
function getGamesToCount() {
    //what types of element do you want to check?
    var elementsToCheck = new Array('div','span');
    
    //this counter is used as the overall counter of IDs in the array of game IDs / HTML IDs
    var counter = 0;
    
    // i is used to loop over the types of HTML elements we want to check
    for (var i = 0; i < elementsToCheck.length; i++) {
    	var currentElement = document.getElementsByTagName(elementsToCheck[i]);
    	// j is used to loop over the instances of a specific type of element in the current DOM
    	for (var j=0; j < currentElement.length; j++) {
    		if (currentElement[j].className == 'gamecount') {
				var currentGameID = currentElement[j].id.replace(/.*_gamecount_/g,'');    			
    			htmlIDsToUpdateWithCounts[counter + currentGameID] = currentElement[j].id;
    			gameIDsToCount[counter] = currentGameID;
    			counter++;
    		}
    	}
    }
}

/**
* wrapper function
*/
function initUserCounts() {
	//find out what games we need counts for
	getGamesToCount();
	//check that gameIDsToCount isn't empty
	//get the game counts in batches
	//update the DOM
	if (gameIDsToCount.length > 0) {
		getGameCountsInBatches();	
	}
}

/**
 * TODO:
 */
function getGameCountsInBatches () {
	var batchOfGameIDs = new String("");
	
	for (var i = 0; i < gameIDsToCount.length; i++) {
		//if this is the overall service gameID, then send it on its own
		if (gameIDsToCount[i].indexOf(OVERALLGAMECOUNTID) != -1) {
			getGameCounts(OVERALLGAMECOUNTID );
		} else {
			// if i is divisible by 10 or it is the last loop, then add the currentGameID to the current batch
			// increment gameIDsToCountIndex, and push the temporary string into the global array
			// clear out the temporary string
			if ((i + 1) % BATCHSIZEFORGAMECOUNTS == 0 || i == gameIDsToCount.length - 1) {
				batchOfGameIDs += gameIDsToCount[i];
				getGameCounts(batchOfGameIDs);
				batchOfGameIDs = '';
			} else { // else just add the currentGameID to the current batch
				batchOfGameIDs += gameIDsToCount[i]  + ',';
			}
		}
	}
}




/**
 * Util to test whether current document is in a frame or not
 * @return {boolean}
 */
function inIframe() {
	if (self != top) {
		return true;
	} else {
		return false;
	}
}

/**
 * get recommendations for a game
 * @param gameId
 * 		for which game do you want to see recos?
 * @param gameType 
 * 		web or download?
 * @param number
 * 		how many recos do you want?
 */
function getGameRecommendations (gameId, gameType, number, element) {
 	var params = new Array();
 	params['gameId'] = gameId;
 	params['gameType'] = gameType;
 	params['ts'] = returnTimeStampString();
 	var bindArgs = {
  		url: returnCorrectprotocolURL(communityBaseurl + "getGameRecos.json"),
  		error: function(type, data, evt){
    		;
   	 	},
   	 	load: function(type, data, evt) {
			onlineGamePageRecos(data, number, element);
		},
		//preventCache: true,
  		timeoutSeconds: TIMEOUTSECONDS,
		timeout: function(type, data, evt){
			;
		},
  		mimetype: "text/json",
  		content: params
 	};
 	var req = dojo.io.bind(bindArgs);
}

/**
 * TODO:
 */
function onlineGamePageRecos (data, number, element) {
	var recommendedGames = eval(data.recommendedGames);
	var recommendedGamesElement = document.getElementById(element);
	var header = document.createElement('h2');
	header.innerHTML = mightLike;
	document.getElementById('recommendationsHeader').appendChild(header);
	//recommendedGamesElement.appendChild(header);
	if (recommendedGames.length > 0) {
		for (var i=0; i < number; i++) {
			var currentGameId = recommendedGames[i].id;
			var path = contextPath + 'games/online/' + currentGameId;
			var currentImagePath = recommendedGames[i].gameImageLocationTinySquare;
			var currentGameName = recommendedGames[i].name;
			var gameDivImg = document.createElement("div");
			gameDivImg.className = 'recommendedGameImg';

			var a1 = document.createElement('a');
			a1.href = path;
			a1.title = currentGameName;

			var image = document.createElement("img");
			image.src = currentImagePath;
			image.alt = currentGameName;
			image.className = 'gameImageLocationTinySquare';
			a1.appendChild(image);
			gameDivImg.appendChild(a1);
			recommendedGamesElement.appendChild(gameDivImg);
			
			var gameDiv = document.createElement("div");
			gameDiv.className = 'recommendedGameInfo';
			var h3 = document.createElement('h3');
			var a2 = document.createElement('a');
			a2.href = path;
			a2.title = currentGameName;
			a2.innerHTML = currentGameName;
			h3.appendChild(a2);
			gameDiv.appendChild(h3);
			var a3 = document.createElement('a');
			a3.href = path;
			a3.title = currentGameName;
			a3.className = 'moreInfo';
			a3.innerHTML = '&raquo;' + moreInfo;
			gameDiv.appendChild(a3);
			recommendedGamesElement.appendChild(gameDiv);
			document.getElementById('recommendationsWrapper').style.display = '';
		}
		var clearer = document.createElement('br');
		clearer.className = 'clearer';
		recommendedGamesElement.appendChild(clearer);
	} else {
		document.getElementById('recommendationsWrapper').style.display = 'none';
	}
}

/**
 * A function to build a pixel ping to the J2Play service to keep a user logged in
 * @param {String} sessionid is the concatenation of the sessionid + gameid
 * @param {String} guid is the user unique ID
 * @param {String} screenname is the user screenname
 * @param {String} tps is the tps of the current user
 * @param {String} gameid is the gameid currently being played
 * @param {String} baseurl is the base J2Play url
 */
function keepAlive (sessionid, guid, screenname, tps, gameid, baseurl) {
	var htmlElementId = 'ping_' + gameid;
	try {
		var url = baseurl;
		url += 'sessionid=' + sessionid + gameid +  '&tps=' + tps + '&gameid=' + gameid + '&ts=' + returnTimeStampString();
		url += (guid != '')?'&guid=' + guid :'';
		url += (screenname != '')?'&screenname=' + screenname :'';
		url = returnCorrectprotocolURL(url);
		
		if (document.getElementById(htmlElementId)) {
			//page already loaded, so just update the src using timestamp to avoid caching
			document.getElementById(htmlElementId).src = url;
		} else {
			//first time page has loaded, so update DOM
			var ping = document.createElement('img');
			ping.className = 'ping';
			ping.id = htmlElementId;
			ping.style.display = 'none';
			ping.style.height = '1px';
			ping.style.width = '1px';
			ping.src = url;
			document.body.appendChild(ping);
		}
	} catch(e) {
		;
	}
}

/**
 * Function to programmatically build iframe for registration or sign-in
 */
function returnModalDialog(dialogId) {
	var modalDialog = dojo.widget.createWidget ("Dialog", {
	    bgOpacity: 0.5,
	    toggle: "fade",
	    toggleDuration: 250,
	    id: dialogId,
	    isContainer: true,
	    followScroll: true
	});
	return modalDialog;
}

/**
 * TODO:
 */
function returnDialogCloser(dialogCloserId) {
	var closer = document.createElement('a');
    closer.setAttribute('href','#');
    closer.setAttribute('id',dialogCloserId);
    var closerImage = document.createElement('img');
    closerImage.setAttribute('src', staticFileBase + 'images/overlayCloseButton_22x23.gif');
    closer.className = 'closer';
    if (jsLocStrings['community_close_window']) {
    	closer.title = jsLocStrings['community_close_window'];
    	closerImage.title = jsLocStrings['community_close_window'];
    	closerImage.alt = jsLocStrings['community_close_window'];
    } else {
    	closer.title = 'X';
    	closerImage.title = 'X';
    	closerImage.alt = 'X';
    }
    closer.appendChild(closerImage);
    return closer;
}

function returnDialogTextCloser(dialogCloserId) {
	var closer = document.createElement('a');
    closer.setAttribute('href','#');
    closer.setAttribute('id',dialogCloserId + 'text');
	closer.appendChild( document.createTextNode(jsLocStrings['community_close_window']) );
    closer.className = 'closerText';
    return closer;
}

/**
 * TODO:
 */
function returnModalIframe(iframeid) {
	var modalIframe = document.createElement('iframe');
	//it is vital that this property is set with a camel case
	//See: http://www.visible-form.com/blog/createelement-and-events-and-iframe-borders/
	modalIframe.frameBorder = 0;
    modalIframe.setAttribute('id',iframeid);
    modalIframe.setAttribute('name',iframeid);
    modalIframe.setAttribute('src',eval(IFRAME_INIT[iframeid]).src);
    modalIframe.setAttribute('frameborder','0');
    modalIframe.setAttribute('scrolling','no');
    modalIframe.setAttribute('marginwidth','0');
    modalIframe.setAttribute('marginheight','0');
    modalIframe.setAttribute('border','0');
    modalIframe.style.border = 'none';
    modalIframe.className = 'modalIframe';
    return modalIframe;
}

/**
 * TODO:
 */
function resetIframe(iframeId) {
	var myIframe = document.getElementById(iframeId);
	myIframe.src = eval(IFRAME_INIT[iframeId]).src;
}

/**
 * TODO:
 */
function createIframeOnClickCallBack(iframeId) {
	return function(evt) {resetIframe(iframeId, evt);};
}

/**
 * TODO:
 */
function returnModalHeader (iframeId) {
	var header = document.createElement('div');
	header.className = iframeId + 'Header';
	header.style.backgroundImage = "url('" + eval(IFRAME_INIT[iframeId]).headerImg + "')";
	//header.setAttribute('style', 'background-image: url(' + eval(IFRAME_INIT[iframeId]).headerImg + ')');
	return header;
}

/**
 * TODO:
 */
function returnModalFooter (iframeId) {
	var footer = document.createElement('div');
	footer.className = iframeId + 'Footer';
	footer.style.backgroundImage = "url('" + eval(IFRAME_INIT[iframeId]).footerImg + "')";
	//footer.setAttribute('style', 'background-image: url(' + eval(IFRAME_INIT[iframeId]).footerImg + ')');
	return footer;
}

/**
 * TODO:
 */
function buildAndShowModal(dialogId) {
	var dialogCloserId = dialogId + 'Hider';
	var iframeId = dialogId + 'Iframe';
	var closer;
	var callback = function () {
 		var modalDialog = returnModalDialog(dialogId);
 		closer = returnDialogCloser(dialogCloserId);
		var modalIframe = returnModalIframe(iframeId);
		var header = returnModalHeader(iframeId);
		header.appendChild(closer);
		var footer = returnModalFooter(iframeId);
		modalDialog.domNode.appendChild(header);
		//modalDialog.domNode.appendChild(closer);
    	modalDialog.domNode.appendChild(modalIframe);
    	modalDialog.domNode.appendChild(footer);
    	modalDialog.domNode.style.backgroundColor = 'transparent';
    	document.body.appendChild(modalDialog.domNode);
    	
    	var myIframe = document.getElementById(iframeId);
	    var dialog = dojo.widget.byId(dialogId);
	    closer = document.getElementById(dialogCloserId);
	    var iframeCallBackFunction = createIframeOnClickCallBack(iframeId);
	    dojo.event.connect(closer, 'onclick', iframeCallBackFunction);
		dialog.setCloseControl(closer);
		closer2 = returnDialogTextCloser(dialogCloserId);
		modalDialog.domNode.appendChild(closer2);			
	    dojo.event.connect(closer2, 'onclick', iframeCallBackFunction);
		dialog.setCloseControl(closer2);		

		var newWidth, newHeight;
	    //if the IFRAME_INIT object does not have the height/width defined then use the default
	    if (eval(IFRAME_INIT[iframeId]).height == 0) {
	    	newHeight = dojo.html.getViewport().height * 80/100;
	    } else {
	    	newHeight = eval(IFRAME_INIT[iframeId]).height;
	    }
	    
	    if (eval(IFRAME_INIT[iframeId]).width == 0) {
	    	newWidth = dojo.html.getViewport().width * 70/100;
	    } else {
	    	newWidth = eval(IFRAME_INIT[iframeId]).width;
	    }
	
	    //var leftForCloser = newWidth - 30;
	    //closer.style.left = leftForCloser + 'px';
		dojo.html.setContentBox(myIframe, {width: newWidth, height: newHeight});
		dialog.show();
 	};
 	dojo.require("dojo.widget.Dialog");
 	dojo.addOnLoad(callback);
}

/**
 * Function to display modal dialog for registration
 */
function initModal(dialogId) {
	//var dialogId = dialogId;
    if (!document.getElementById(dialogId)) {
    	buildAndShowModal(dialogId);
    } else {
    	var myIframe = document.getElementById(dialogId + 'Iframe');
    	if (myIframe.src != eval(IFRAME_INIT[dialogId + 'Iframe']).src) {
    		myIframe.src = eval(IFRAME_INIT[dialogId + 'Iframe']).src;
    	} 
    	var dialog = dojo.widget.byId(dialogId);
    	dialog.show();
    }
}

/**
 * TODO:
 */
function toggleTip(elementId){
	var elementToToggleDisplay = document.getElementById(elementId);
	if (dojo.html.isDisplayed(elementToToggleDisplay)) {
		dojo.html.setDisplay(elementToToggleDisplay, 'none');
	} else {
		dojo.html.setDisplay(elementToToggleDisplay, '');
	}
}

/**
 * TODO:
 */
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

/**
 * When called from an iframe in a modal dialog in its parent window
 * this function will hide one dialog, reset that dialog to its initial
 * URL, and then show the newly requested dialog
 * @param {String} from is the HTML id attribute of the dialog to hide and reset
 * @param {String} to  is the HTML id attribute of the dialog to show
 */
function changeModal(from, to) {
	parent.hideDialog(from);
	parent.resetIframe(from + 'Iframe');
	parent.initModal(to);
}

/**
 * Hides a dojo modal dialog on request
 * @param {String} dialogId is the HTML id attribute of the dialog to hide
 */
function hideDialog(dialogId) {
	var callback = function () {
		var dialogToClose = dojo.widget.byId(dialogId);
		dialogToClose.hide();
	};
	dojo.require("dojo.widget.Dialog");
	dojo.addOnLoad(callback);
}

function createCookie(name,value,days,path) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=" + path;
}

function killDiscKnown() {
	createCookie('DiscKnown','',-1,'/');
}

function killJSESSIONID() {
	if (location.port == '8080' || location.port == '8443') {
 		createCookie('JSESSIONID','',-1,'/games');
 	} else {
 		createCookie('JSESSIONID','',-1,'/');
 	}
}

function logout() {
	killDiscKnown();
	killJSESSIONID();		
	document.location.reload();
}

function returnCorrectprotocolURL (url) {
	var curProtocol = window.location.protocol;
	if (curProtocol.toLowerCase() == 'https:') {
		url = url.toLowerCase();
		url = url.replace('http:','https:');
	} 
	return url;
}
