/**************************************************************************************
* File: dataServices.js
*
* These are the backend data service calls to retrieve data for the UI.
*
* NOTE ON DEBUGGING:!!!: When you see wierd exceptions in "data service..." code, it is almost
* always due to a parsed XML response having a comment in front of the "root" element we are looking
* for.  A fix would be to repair the way all of our "model" objects find their "root" element as they are
* marshalled from XML into JavaScript.
*
***************************************************************************************/

//alert ( "BEGIN LOAD DATA SERVICES" );

var m_dataServiceTraceString = "";
var m_doNotShowFatalErrorMessage = false;


var DataServiceBackEnd = {
	DUMMY_DATA:false,

	GAME_SERVER_URL:"/vbgame/gameserver.htm",
	
	toString:function () {
		return "DUMMY_DATA: " + this.DUMMY_DATA + ", GAME_SERVER_URL: " + this.GAME_SERVER_URL;
	}
};



// m_webAppSessionId

function appendWebAppSessionIdToUrlIfNecessary ( origUrl ) {
	var modifiedUrl = origUrl;
	
	if ( m_webAppSessionId != null ) {
		if ( modifiedUrl.indexOf ( "?" ) >= 0 ) {
			modifiedUrl += "&webAppSessionId=" + m_webAppSessionId;
		} else {
			modifiedUrl += "?webAppSessionId=" + m_webAppSessionId;
		}
	}
	
	return modifiedUrl;
	
}

function appendAffiliateIdToUrlIfNecessary ( origUrl ) {
	var modifiedUrl = origUrl;
	
	var _affiliateId = null;
	
	try {
		if ( this["m_affiliateId" ] && m_affiliateId != null ) {
			_affiliateId = this["m_affiliateId" ];
		}
	} catch ( exc ) {
		//alert ( "EXC: " + exc );
	}
	
	//alert ( "_affiliateId: " + _affiliateId );
	
	if ( _affiliateId != null ) {
		if ( modifiedUrl.indexOf ( "?" ) >= 0 ) {
			modifiedUrl += "&affiliateId=" + _affiliateId;
		} else {
			modifiedUrl += "?affiliateId=" + _affiliateId;
		}
	}
	
	return modifiedUrl;
	
}



/**************************
*
* Sandwich the call to "callDataService".  If it doesn't return within a specific window, try again once.  OK?...
*
***************************/

var m_watch_retryNumber = 0;
var m_watch_requestParmsObject = null;
var m_watch_requestXML = null;
var m_watch_responseClass = null;
var m_watch_endPointURL = null;
var m_watch_callback = null;
var m_watch_expectedResponseCodes = null;
var m_watch_didCompleteAjaxCall = false;
// DOESNT WORK IN IE WHEN THIS IS DECLARED WITH A VAR AND WE DO THE MAGIC CRAP WE DO... var m_watch_timerId = null;

/**
* This used to be 5 seconds, which was a fine amount of time to wait for those few cases where the game and Ajax really did "drop" the message
* and the user didn't see any response from the game for 5 seconds, then the game resent and all was well.
*
* BUT!!! At the end of a game, it sometimes actually takes the server 5 seconds to process before returing to us.  So we'd send a duplicate
* ANSWER message to the back end at the end of the game and really the back end would have received our initial message, so our resend is a 
* DUP and breaks the state of the back end.
*
* So, this is now at 10 seconds for now!!!
*
* SLW UPDATE: 11/12/08.  As of this time, they have fixed the back end speed issues with the end of game.  So we can reduce the amount of
* time that the game waits before resending an ajax call back down to 5 seconds.  This will yield better performance for those situations
* where the game really did drop an ajax call during "get question" or "answer."
*/
var TIMEOUT_FOR_COMPLETING_AJAX_CALL = 5000; //10000; // 10000; //20000; // Milliseconds.

function handleDataServiceCallTimeout () {

//alert ( "TIMEOUT CALLED m_someOtherValue: " + window.m_watch_timerIdNotDeclaredWithVar );

//alert ( " idOfWatchTimer: " + window.idOfWatchTimer );

   window.idOfWatchTimer = null;

//alert ( "Data service call timeout, m_watch_didCompleteAjaxCall: " + m_watch_didCompleteAjaxCall );
	
	window.m_watch_timerIdNotDeclaredWithVar = null;
	
	if ( m_watch_didCompleteAjaxCall ) {
		
m_dataServiceTraceString += "Ajax call timeout handler.  Call succeeded.";  

      m_watch_retryNumber = Number(0);
      m_watch_requestParmsObject = null;
		m_watch_requestXML = null;
		m_watch_responseClass = null;
		m_watch_endPointURL = null;
		m_watch_callback = null;
		m_watch_expectedResponseCodes = null;		
	} else {
		
m_dataServiceTraceString += "Ajax call timeout.  Trying ajax call again...";

/**
* New, SLW 9/11/08.  Add a little "retry" flag.
*/
      m_watch_retryNumber = Number(m_watch_retryNumber) + 1;
		m_watch_requestParmsObject.retry = m_watch_retryNumber;
		m_watch_requestXML = "<vbrequest ";
		for ( var p in m_watch_requestParmsObject ) {
			m_watch_requestXML += " " + p + "='" + m_watch_requestParmsObject[p] + "' ";
		}
		m_watch_requestXML += " />";
/**
* End of new
*/

		// alert ( "We had trouble sending your last response.  \r\nPlease click and we'll try again." );
		if ( m_watch_didCompleteAjaxCall == false ) {
		   callDataService ( m_watch_requestXML, m_watch_responseClass, m_watch_endPointURL, m_watch_callback, m_watch_expectedResponseCodes );
		}
	}
}

/**
* This funny mechanism is a hack.  There seem to be some times when the first time we either do a "get question" (after the user clicked on the gameboard)
* or a "get answer" (after the user has answered a question) the Ajax message doesn't ever get sent over the network.  In such cases, the game
* freezes.  
*
* What we are doing here is setting a timer before making one of those 2 ajax calls.  If the timer "dings" and the ajax call has not returned, we
* assume it was never sent.  In such a situation, we put up a dialog box telling them to "click to resend your response".
*/
function watchedCallDataService  ( requestXML, responseClass, endPointURL, callback, expectedResponseCodes, requestParmsObject ) {
	
	
m_dataServiceTraceString += "Making 'watched' ajax call";

   m_watch_retryNumber = Number(0);
   m_watch_requestParmsObject = requestParmsObject;

	m_watch_requestXML = requestXML;
	m_watch_responseClass = responseClass;
	m_watch_endPointURL = endPointURL;
	m_watch_callback = callback;
	m_watch_expectedResponseCodes = expectedResponseCodes;
	
	m_watch_didCompleteAjaxCall = false;
	
	try {
//alert ( "ABOUT TO CHECK" );
	   if ( window.idOfWatchTimer != null ) {
		  clearTimeout (window.idOfWatchTimer);
		  window.idOfWatchTimer = null;
	   }
	} catch ( excHide ) {
	}
	
//alert ( " m_watch_timerId: " + window.m_watch_timerId );

//alert ( "THIS: " + this.location.href );
    
	// window.m_watch_timerId  = 456;
	 //window.m_watch_timerIdNotDeclaredWithVar = setTimeout ( handleDataServiceCallTimeout, 100 );	
	 
	 /**
	 *
	 * NOTE TO SELF: 
	 *  1) If we did this in one step (such as window.idOfWatchTimer = setTimeout (...)) the timeout function was
	 *     never called from within IE.
	 *  2) And it seemed that if that variable "idOfWatchTimer" was declared with a "var" statement, it wouldn't work in IE even
	 *     if we did this in two steps like this.  So "idOfWatchTimer" is not declared with a "var" statement.
	 */
	 var timerId = setTimeout ( handleDataServiceCallTimeout, TIMEOUT_FOR_COMPLETING_AJAX_CALL );	
	 
	// window["m_watch_timerIdNotDeclaredWithVar"] = timerId;
	 
	 window.idOfWatchTimer = timerId;
	 
//alert ( "AFTER SET TIMEOUT timerId: " + window.m_someOtherValue );

  //   window.m_someOtherValue = timerId;
	 
    //  window.m_watch_timerId = Number(timerId);
	
//	m_watch_timerId = setTimeout ( handleDataServiceCallTimeout, 1 ); // TIMEOUT_FOR_COMPLETING_AJAX_CALL );

//alert ( " m_watch_timerId:  " + m_watch_timerId );
	
	callDataService ( requestXML, responseClass, endPointURL, callback, expectedResponseCodes );
}


/****************************************************************
*
* "GET_RECOMENDATIONS"
*
*****************************************************************/


function dataService_getSuggestedNextGames ( callback, pjuid, gameId ) {
	var requestXML = "<vbrequest code=\"GET_RECOMMENDATIONS\" pjuid=\"" + pjuid + "\" gameId=\"" + gameId + "\" count=\"" + m_numberOfSuggestedGamesToShow + "\"/>";
	
// alert ( " requestXML:  " + requestXML );

	var url = DataServiceBackEnd.GAME_SERVER_URL; 
	
//DataServiceBackEnd.DUMMY_DATA = true;
//alert ( " DataServiceBackEnd.DUMMY_DATA: " + DataServiceBackEnd.DUMMY_DATA );	
	if ( DataServiceBackEnd.DUMMY_DATA ) {
	   url = "./dummyData/getSuggestedNextGames.xml"
	}
//DataServiceBackEnd.DUMMY_DATA = false;	
	
	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);
	
//alert ( " URL: " + url );	
	
	var expectedResponseCodes = [
		"GET_RECOMMENDATIONS_OK"
	]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, SuggestedNextGamesResponse, url , callback, expectedResponseCodes );
}




/****************************************************************
*
* "GET_EMAIL_CONTACT_LIST" User From Game Server Data
*
*****************************************************************/


function getEmailContactList ( callback, userEmail, userEmailPassword ) {
	var requestXML = "<vbrequest code='GET_EMAIL_CONTACT_LIST' userEmail='" + userEmail + "' userEmailPassword='" + userEmailPassword + "' />";
	var url = "/videocube/getEmailContactList.jsp"; //DataServiceBackEnd.GAME_SERVER_URL; // "./dummyData/getUserInfo.xml"
	
	///DataServiceBackEnd.GAME_SERVER_URL;
	//if ( DataServiceBackEnd.DUMMY_DATA ) {
	//	url = "./dummyData/getUserStats.xml"
	//}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"GET_EMAIL_CONTACT_LIST_OK", "GET_EMAIL_CONTACT_LIST_ERROR"
	]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, WebEmailContactListResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "GET_USER" Data
*
*****************************************************************/

function dataService_getUser ( callback, pjuid ) {
	
	var requestXML = null;
	
    if ( pjuid && pjuid != null && pjuid != "null" ) {
		requestXML = "<vbrequest code='GET_USER' pjuid='" + pjuid + "' />";
	} else {
		requestXML = "<vbrequest code='GET_USER' />";
	}


    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/UserInfo.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);
	
	url = appendAffiliateIdToUrlIfNecessary (url);

	
	var expectedResponseCodes = [
		"GET_USER_OK", "UNREGISTERED_USER"
	]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GetUserResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "START GAME"
*
*****************************************************************/

function dataService_startGame ( callback, parms ) {
	
	var requestXML = buildRequestFromParms ( "START_GAME", parms ) 
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	 
	 if ( parms.origin == "facebook" ) {
		 url += "?affiliateId=2";
	 }
	 
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		if ( parms.gameType == "HIT" ) {
			if ( this["dummyGameFile"] ) {
			   url = this["dummyGameFile"];
			} else {
		       url = "./dummyData/3x3Game.xml";
			}
		} else {
			url = "./dummyData/4x4Game.xml";
		}
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);


/*
"facebook"
*/
	
	var expectedResponseCodes = [
		"GAME_OK", "GAME_ALREADY_PLAYED"
	]
	
	var responseClasses = new Object ();
	responseClasses.GAME_OK = StartGameResponse;
	responseClasses.GAME_ALREADY_PLAYED = GameAlreadyPlayedResponse;
	
	/*
	callDataServiceMultiResponseClasses
	*/
	
	clearDupResponseHandlingFlags ();
	callDataServiceMultiResponseClasses ( requestXML, responseClasses, url , callback, expectedResponseCodes );
}


var m_getQuestionCallOutstanding = false;
var m_getQuestionCallResponseReceived = false;
var m_getAnswerCallOutstanding = false;
var m_getAnswerCallResponseReceived = false;

function clearDupResponseHandlingFlags () {
	m_getQuestionCallOutstanding = false;
	m_getQuestionCallResponseReceived = false;
	m_getAnswerCallOutstanding = false;
   m_getAnswerCallResponseReceived = false;
}

/****************************************************************
*
* "GET QUESTION" Data
*
*****************************************************************/
function dataService_getQuestion ( callback, xPos, yPos ) {
	
	
	var requestParms  = { 
	    code:"GET_QUESTION",
		 pos:xPos + " " + yPos
	};
	
	var requestXML = "<vbrequest ";
	for ( var p in requestParms ) {
		requestXML += " " + p + "='" + requestParms[p] + "' ";
	}
	requestXML += " />";



//	var requestXML = "<vbrequest code='GET_QUESTION' pos=" + "'" + xPos + " " + yPos + "' />";

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	
//alert ( " DataServiceBackEnd.DUMMY_DATA: " + DataServiceBackEnd.DUMMY_DATA );

	if ( DataServiceBackEnd.DUMMY_DATA ) {
		if ( this["dummyGameFile"] ) {
			var gameFilePrefix = this["dummyGameFilePrefix"];

			if ( xPos == 0 && yPos == 0 ) { url = "./dummyData/" + gameFilePrefix + "Question1.xml"; }
			if ( xPos == 1 && yPos == 0 ) { url = "./dummyData/" + gameFilePrefix + "Question2.xml"; }
			if ( xPos == 2 && yPos == 0 ) { url = "./dummyData/" + gameFilePrefix + "Question3.xml"; }
			if ( xPos == 3 && yPos == 0 ) { url = "./dummyData/" + gameFilePrefix + "Question3.xml"; }
			if ( xPos == 0 && yPos == 1 ) { url = "./dummyData/" + gameFilePrefix + "Question4.xml"; }
			if ( xPos == 1 && yPos == 1 ) { url = "./dummyData/" + gameFilePrefix + "Question5.xml"; }
			if ( xPos == 2 && yPos == 1 ) { url = "./dummyData/" + gameFilePrefix + "Question6.xml"; }
			if ( xPos == 3 && yPos == 1 ) { url = "./dummyData/" + gameFilePrefix + "Question6.xml"; }
			if ( xPos == 0 && yPos == 2 ) { url = "./dummyData/" + gameFilePrefix + "Question7.xml"; }
			if ( xPos == 1 && yPos == 2 ) { url = "./dummyData/" + gameFilePrefix + "Question8.xml"; }
			if ( xPos == 2 && yPos == 2 ) { url = "./dummyData/" + gameFilePrefix + "Question9.xml"; }
			if ( xPos == 3 && yPos == 2 ) { url = "./dummyData/" + gameFilePrefix + "Question9.xml"; }
			if ( xPos == 0 && yPos == 3 ) { url = "./dummyData/" + gameFilePrefix + "Question7.xml"; }
			if ( xPos == 1 && yPos == 3 ) { url = "./dummyData/" + gameFilePrefix + "Question8.xml"; }
			if ( xPos == 2 && yPos == 3 ) { url = "./dummyData/" + gameFilePrefix + "Question9.xml"; }
			if ( xPos == 3 && yPos == 3 ) { url = "./dummyData/" + gameFilePrefix + "Question9.xml"; }		

        } else {
			if ( xPos == 0 && yPos == 0 ) { url = "./dummyData/HitGameQuestion1.xml"; }
			if ( xPos == 1 && yPos == 0 ) { url = "./dummyData/HitGameQuestion2.xml"; }
			if ( xPos == 2 && yPos == 0 ) { url = "./dummyData/HitGameQuestion3.xml"; }
			if ( xPos == 3 && yPos == 0 ) { url = "./dummyData/HitGameQuestion3.xml"; }
			if ( xPos == 0 && yPos == 1 ) { url = "./dummyData/HitGameQuestion4.xml"; }
			if ( xPos == 1 && yPos == 1 ) { url = "./dummyData/HitGameQuestion5.xml"; }
			if ( xPos == 2 && yPos == 1 ) { url = "./dummyData/HitGameQuestion6.xml"; }
			if ( xPos == 3 && yPos == 1 ) { url = "./dummyData/HitGameQuestion6.xml"; }
			if ( xPos == 0 && yPos == 2 ) { url = "./dummyData/HitGameQuestion7.xml"; }
			if ( xPos == 1 && yPos == 2 ) { url = "./dummyData/HitGameQuestion8.xml"; }
			if ( xPos == 2 && yPos == 2 ) { url = "./dummyData/HitGameQuestion9.xml"; }
			if ( xPos == 3 && yPos == 2 ) { url = "./dummyData/HitGameQuestion9.xml"; }
			if ( xPos == 0 && yPos == 3 ) { url = "./dummyData/HitGameQuestion7.xml"; }
			if ( xPos == 1 && yPos == 3 ) { url = "./dummyData/HitGameQuestion8.xml"; }
			if ( xPos == 2 && yPos == 3 ) { url = "./dummyData/HitGameQuestion9.xml"; }
			if ( xPos == 3 && yPos == 3 ) { url = "./dummyData/HitGameQuestion9.xml"; }		
		}
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"GET_QUESTION_OK"
	]
	
/**
* This funny mechanism is a hack.  There seem to be some times when the first time we either do a "get question" (after the user clicked on the gameboard)
* or a "get answer" (after the user has answered a question) the Ajax message doesn't ever get sent over the network.  In such cases, the game
* freezes.  
*
* What we are doing here is setting a timer before making one of those 2 ajax calls.  If the timer "dings" and the ajax call has not returned, we
* assume it was never sent.  In such a situation, we put up a dialog box telling them to "click to resend your response".
*/	
    //setTimeout ( callMeLater, 100 );	
	 
	 clearDupResponseHandlingFlags ();
	m_getQuestionCallOutstanding = true;
	m_getQuestionCallResponseReceived = false;
	 
	watchedCallDataService ( requestXML, QuestionResponse, url , callback, expectedResponseCodes, requestParms );
	
	// callDataService ( requestXML, QuestionResponse, url , callback, expectedResponseCodes );
}




/****************************************************************
*
* "GET QUESTION BY ID" Data
*
*****************************************************************/
function dataService_getQuestionById ( callback, questionId ) {
	var requestXML = "<vbrequest code='GET_QUESTION_BY_ID' id=" + "'" + questionId + "' />";

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	
//alert ( " DataServiceBackEnd.DUMMY_DATA: " + DataServiceBackEnd.DUMMY_DATA );

	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/HitGameQuestion1.xml";
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);


	var expectedResponseCodes = [
		"GET_QUESTION_OK"
	]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, QuestionResponse, url , callback, expectedResponseCodes );
}



/****************************************************************
*
* "SEND USER FEEDBACK"
*
*****************************************************************/
function dataService_userFeedback ( callback, emailAddress, feedback ) {
	
	var requestXML = "<vbrequest code='USERFEEDBACK' fromAddr='" + emailAddress + "' comments=" + "'" + feedback + "' />";

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/RateQuestionOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"OK"
	]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "VideoPlayed" 
*
*****************************************************************/

function dataService_videoPlayed ( callback, col, row, videoPlayedTime, videoPlayStatus ) {
	

    var requestParms  = { 
	      code:"VideoPlayed",
	    	pos:col + " " + row,
	    	videoPlayedTime:videoPlayedTime,
	    	videoPlayStatus:videoPlayStatus
	};	
	
	var requestXML = "<vbrequest ";
	for ( var p in requestParms ) {
		requestXML += " " + p + "='" + requestParms[p] + "' ";
	}
	requestXML += " />";
	

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/RateQuestionOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);


	var expectedResponseCodes = [
		"VideoPlayedOk", "VideoPlayedOK", "OK"
	]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "GET ANSWER" 
*
*****************************************************************/

function dataService_getAnswer ( callback, col, row, userAnswerArrayString, scale, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
//	alert ( " userAnswerArrayString: " + userAnswerArrayString );
	
	userAnswerArrayString = String(userAnswerArrayString);
	
	var userAnswerArray = userAnswerArrayString.split(",");
	var answerData = userAnswerArray.join ( " " );
	
	// Trac 885 - April 2009
	answerData = answerData.replace ( /'/g, "&apos;" ) ;
	answerData = answerData.replace ( /&/g, "&amp;" ) ;
	
//alert ( "GET ANSWER userAnswerQuestionTime: " + userAnswerQuestionTime );

    var requestParms  = { 
	        code:"ANSWER",
	    	pos:col + " " + row,
	    	answer:answerData,
	    	scale:scale,
			videoLoadedTime:videoLoadedTime,
			userAnswerQuestionTime:userAnswerQuestionTime,
			videoLoadStatus:videoLoadStatus
	};	
	
	var requestXML = "<vbrequest ";
	for ( var p in requestParms ) {
		requestXML += " " + p + "='" + requestParms[p] + "' ";
	}
	requestXML += " />";
	
// alert ( "REQUEST: " + requestXML );

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		if ( col == 0 && row == 0 ) { url = "./dummyData/HitGameAnswer1.xml"; }
		if ( col == 1 && row == 0 ) { url = "./dummyData/HitGameAnswer2.xml"; }
		if ( col == 2 && row == 0 ) { url = "./dummyData/HitGameAnswer3.xml"; }
		if ( col == 3 && row == 0 ) { url = "./dummyData/HitGameAnswer3.xml"; }
		if ( col == 0 && row == 1 ) { url = "./dummyData/HitGameAnswer4.xml"; }
		if ( col == 1 && row == 1 ) { url = "./dummyData/HitGameAnswer5.xml"; }
		if ( col == 2 && row == 1 ) { url = "./dummyData/HitGameAnswer6.xml"; }
		if ( col == 3 && row == 1 ) { url = "./dummyData/HitGameAnswer6.xml"; }
		if ( col == 0 && row == 2 ) { url = "./dummyData/HitGameAnswer7.xml"; }
		if ( col == 1 && row == 2 ) { url = "./dummyData/HitGameAnswer8.xml"; }
		if ( col == 2 && row == 2 ) { url = "./dummyData/HitGameAnswer9.xml"; }
		if ( col == 3 && row == 2 ) { url = "./dummyData/HitGameAnswer9.xml"; }
		if ( col == 0 && row == 3 ) { url = "./dummyData/HitGameAnswer7.xml"; }
		if ( col == 1 && row == 3 ) { url = "./dummyData/HitGameAnswer8.xml"; }
		if ( col == 2 && row == 3 ) { url = "./dummyData/HitGameAnswer8.xml"; }
		if ( col == 3 && row == 3 ) { url = "./dummyData/HitGameAnswer9.xml"; }
		
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"ANSWER_INCORRECT", "ANSWER_CORRECT", "GAME_WON", "GAME_LOST", "BLACKOUT_FINISH"
	];
	

/**
* This funny mechanism is a hack.  There seem to be some times when the first time we either do a "get question" (after the user clicked on the gameboard)
* or a "get answer" (after the user has answered a question) the Ajax message doesn't ever get sent over the network.  In such cases, the game
* freezes.  
*
* What we are doing here is setting a timer before making one of those 2 ajax calls.  If the timer "dings" and the ajax call has not returned, we
* assume it was never sent.  In such a situation, we put up a dialog box telling them to "click to resend your response".
*/	

    clearDupResponseHandlingFlags ();
   m_getAnswerCallOutstanding = true;
   m_getAnswerCallResponseReceived = false;

	watchedCallDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes, requestParms );
	
	 // callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}


function dataService_getBonusAnswer ( callback, col, row, userAnswerArrayString, scale, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
//	alert ( " userAnswerArrayString: " + userAnswerArrayString );
	
	userAnswerArrayString = String(userAnswerArrayString);
	
	var userAnswerArray = userAnswerArrayString.split(",");
	var answerData = userAnswerArray.join ( " " );
	
	// Trac 885 - April 2009
	answerData = answerData.replace ( /'/g, "&apos;" ) ;
	answerData = answerData.replace ( /&/g, "&amp;" ) ;
	
    var requestParms  = { 
	        code:"ANSWER_BONUS",
	    	pos:col + " " + row,
	    	answer:answerData,
	    	scale:scale,
			videoLoadedTime:videoLoadedTime, 
			userAnswerQuestionTime:userAnswerQuestionTime,
			videoLoadStatus:videoLoadStatus
	};	
	
	var requestXML = "<vbrequest ";
	for ( var p in requestParms ) {
		requestXML += " " + p + "='" + requestParms[p] + "' ";
	}
	requestXML += " />";
	
// alert ( "REQUEST: " + requestXML );

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		if ( col == 0 && row == 0 ) { url = "./dummyData/HitGameAnswer1-wrong.xml"; }
		if ( col == 1 && row == 0 ) { url = "./dummyData/HitGameAnswer2.xml"; }
		if ( col == 2 && row == 0 ) { url = "./dummyData/HitGameAnswer3.xml"; }
		if ( col == 0 && row == 1 ) { url = "./dummyData/HitGameAnswer4.xml"; }
		if ( col == 1 && row == 1 ) { url = "./dummyData/HitGameAnswer5.xml"; }
		if ( col == 2 && row == 1 ) { url = "./dummyData/HitGameAnswer6.xml"; }
		if ( col == 0 && row == 2 ) { url = "./dummyData/HitGameAnswer7.xml"; }
		if ( col == 1 && row == 2 ) { url = "./dummyData/HitGameAnswer8.xml"; }
		if ( col == 2 && row == 2 ) { url = "./dummyData/HitGameAnswer9.xml"; }
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"ANSWER_INCORRECT", "ANSWER_CORRECT", "GAME_WON", "GAME_LOST", "BLACKOUT_FINISH"
	];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}



function dataService_getAnswerPreview ( callback, questionId, userAnswerArrayString, scale, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
//	alert ( " userAnswerArrayString: " + userAnswerArrayString );
	
	userAnswerArrayString = String(userAnswerArrayString);
	
	var userAnswerArray = userAnswerArrayString.split(",");
	var answerData = userAnswerArray.join ( " " );
	
	// Trac 885 - April 2009
	answerData = answerData.replace ( /'/g, "&apos;" ) ;
	answerData = answerData.replace ( /&/g, "&amp;" ) ;

    var requestParms  = { 
	        code:"ANSWER_PREVIEW",
	    	qid:questionId,
	    	answer:answerData,
	    	scale:scale,
			videoLoadedTime:videoLoadedTime, 
			userAnswerQuestionTime:userAnswerQuestionTime,
			videoLoadStatus:videoLoadStatus
	};	
	
	var requestXML = "<vbrequest ";
	for ( var p in requestParms ) {
		requestXML += " " + p + "='" + requestParms[p] + "' ";
	}
	requestXML += " />";
	
// alert ( "REQUEST: " + requestXML );

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/HitGameAnswer1.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"ANSWER_INCORRECT", "ANSWER_CORRECT"
	];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}


function dataService_getBonusAnswerPreview ( callback, questionId, userAnswerArrayString, scale, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
//	alert ( " userAnswerArrayString: " + userAnswerArrayString );
	
	userAnswerArrayString = String(userAnswerArrayString);
	
	var userAnswerArray = userAnswerArrayString.split(",");
	var answerData = userAnswerArray.join ( " " );
	
	// Trac 885 - April 2009
	answerData = answerData.replace ( /'/g, "&apos;" ) ;
	answerData = answerData.replace ( /&/g, "&amp;" ) ;
	
    var requestParms  = { 
	        code:"ANSWER_BONUS_PREVIEW",
	    	qid:questionId,
	    	answer:answerData,
	    	scale:scale,
			videoLoadedTime:videoLoadedTime, 
			userAnswerQuestionTime:userAnswerQuestionTime,
			videoLoadStatus:videoLoadStatus
	};	
	
	var requestXML = "<vbrequest ";
	for ( var p in requestParms ) {
		requestXML += " " + p + "='" + requestParms[p] + "' ";
	}
	requestXML += " />";
	
// alert ( "REQUEST: " + requestXML );

    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		if ( col == 0 && row == 0 ) { url = "./dummyData/HitGameAnswer1.xml"; }
		if ( col == 1 && row == 0 ) { url = "./dummyData/HitGameAnswer2.xml"; }
		if ( col == 2 && row == 0 ) { url = "./dummyData/HitGameAnswer3.xml"; }
		if ( col == 0 && row == 1 ) { url = "./dummyData/HitGameAnswer4.xml"; }
		if ( col == 1 && row == 1 ) { url = "./dummyData/HitGameAnswer5.xml"; }
		if ( col == 2 && row == 1 ) { url = "./dummyData/HitGameAnswer6.xml"; }
		if ( col == 0 && row == 2 ) { url = "./dummyData/HitGameAnswer7.xml"; }
		if ( col == 1 && row == 2 ) { url = "./dummyData/HitGameAnswer8.xml"; }
		if ( col == 2 && row == 2 ) { url = "./dummyData/HitGameAnswer9.xml"; }
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = [
		"ANSWER_INCORRECT", "ANSWER_CORRECT"
	];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "EMAIL QUESTION"
*
*****************************************************************/

function dataService_emailQuestion ( callback, questionId, fromEmail, toEmail, message ) {
	
	var parms = new Object ();
	parms.qid  = questionId;
	parms.from = fromEmail;
	parms.to   = toEmail;
	
	message = message.replace ( /'/g, "&apos;" ) ;
	message = message.replace ( /&/g, "&amp;"  ) ;
	
	parms.notes =  message ;
	
	var requestXML = buildRequestFromParms ( "EMAIL_QUESTION", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/RateQuestionOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["OK"]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "EMAIL GAME"
*
*****************************************************************/

function dataService_emailGame ( callback, gameId, pjuid, gameType, origin, fromEmail, toEmail, message, gamePageId ) {
	
	var parms = new Object ();
	parms.gameId = gameId;
	parms.pjuid = pjuid;
	parms.gameType = gameType;
	parms.origin = origin;
	parms.from = fromEmail;
	parms.to = toEmail;
	
// apos  gameboardSwf = gameboardSwf.replace  ( /GameBoard.swf/, "GameBoardOldSounds.swf" );

    var escapedMessage = message.replace  ( /\'/g, "&apos;" );
	 escapedMessage = escapedMessage.replace  ( /\&/g, "&amp;" );

//alert ( " escapedMessage: " + escapedMessage );

	
	parms.message = escapedMessage;
	if ( gamePageId ) {
		parms.gamePage = gamePageId;
	}
	
	var requestXML = buildRequestFromParms ( "EMAIL_GAME", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/EmailGameOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["EMAIL_GAME_OK", "OK"];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "END GAME"
*
*****************************************************************/

function dataService_endGame ( callback  ) {
	
	var parms = new Object ();
	
	var requestXML = buildRequestFromParms ( "END_GAME", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/EndGameOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["OK", "END_GAME_OK"];
	
	clearDupResponseHandlingFlags ();
	m_doNotShowFatalErrorMessage = true;
	callDataService ( requestXML, EndGameResponse, url , callback, expectedResponseCodes );
	//m_doNotShowFatalErrorMessage = false;
}



/****************************************************************
*
* "GET GAME INFO"
*
*****************************************************************/

function dataService_getGameInfo ( callback, pjuid ) {
	
	var parms = new Object ();
	parms.pjuid = pjuid;
	
	var requestXML = buildRequestFromParms ( "GET_GAME_INFO", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/GameInfo.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["GET_GAME_INFO_OK"];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GameInfoResponse, url , callback, expectedResponseCodes );
}




/****************************************************************
*
* "RATE QUESTION"
*
*****************************************************************/

function dataService_rateQuestion ( callback, questionId, rating ) {
	
	var parms = new Object ();
	//parms.questionId = questionId;
	parms.qid = questionId;
	parms.rating = rating;
	
	var requestXML = buildRequestFromParms ( "RATE_QUESTION", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/RateQuestionOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);


	var expectedResponseCodes = ["OK"]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "MARK AS FAVORITE"
*
*****************************************************************/

function dataService_markQuestionAsFavorite ( callback, questionId ) {
	
	var parms = new Object ();
	//parms.questionId = questionId;
	parms.qid = questionId;
	
	var requestXML = buildRequestFromParms ( "TAG_QUESTION", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/RateQuestionOk.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["OK"]
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );
}


/****************************************************************
*
* "LOCKOUT QUESTION"
*
*****************************************************************/

function dataService_lockoutQuestion ( callback, col, row, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
	var parms = new Object ();
	parms.pos = col + " " + row;
	parms.videoLoadedTime = videoLoadedTime;
	parms.userAnswerQuestionTime = userAnswerQuestionTime;
	parms.videoLoadStatus = videoLoadStatus;
	
	var requestXML = buildRequestFromParms ( "LOCKOUT", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/LockoutResponse.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["ANSWER_INCORRECT", "GAME_WON", "GAME_LOST", "BLACKOUT_FINISH"];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}


function dataService_lockoutBonusQuestion ( callback, col, row, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
	var parms = new Object ();
	parms.pos = col + " " + row;
	parms.videoLoadedTime = videoLoadedTime;
	parms.userAnswerQuestionTime = userAnswerQuestionTime;
	parms.videoLoadStatus = videoLoadStatus;
	
	var requestXML = buildRequestFromParms ( "LOCKOUT_BONUS", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/LockoutResponse.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["ANSWER_INCORRECT", "GAME_WON", "GAME_LOST", "BLACKOUT_FINISH"];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}


function dataService_lockoutPreviewQuestion ( callback, questionId, videoLoadedTime, userAnswerQuestionTime, videoLoadStatus ) {
	
	var parms = new Object ();
	parms.questionId = questionId;
	parms.videoLoadedTime = videoLoadedTime;
	parms.userAnswerQuestionTime = userAnswerQuestionTime;
	parms.videoLoadStatus = videoLoadStatus;
	
	var requestXML = buildRequestFromParms ( "LOCKOUT_PREVIEW", parms);
	
    var url = DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/HitGameAnswer1.xml"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);

	var expectedResponseCodes = ["ANSWER_INCORRECT" ];
	
	clearDupResponseHandlingFlags ();
	callDataService ( requestXML, AnswerResponse, url , callback, expectedResponseCodes );
}



/***************************************
*
* postDataToEndpoint ( requestData, endPointURL, callback ) 
*
****************************************/

function dataService_submitQuestion ( callback, postData ) {
	
	
//	alert ( " dataService_submitQuestion called" );
	
    var url = "/videocube/submitQuestion.htm"; //DataServiceBackEnd.GAME_SERVER_URL;
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/submitQuestionResponse.html"; 
	}

	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
//	url = appendWebAppSessionIdToUrlIfNecessary (url);

	try {
	   postDataToEndpoint ( postData, url, callback );
	} catch ( exc ) {
		alert ( "EXC: " + exc );
	}
}



/****************************************************************
*
* "INVITE PEOPLE TO THE SITE"
*
*****************************************************************/
	
function dataService_emailInvites ( callback, pjuid, name, origin, toEmailAddresses, message, landingPageUrl ) 
{	
	// Trac 885 - April 2009
	name    = name.replace    ( /'/g, "&apos;" ) ;
	name    = name.replace    ( /&/g, "&amp;"  ) ;
	
	message = message.replace    ( /'/g, "&apos;" ) ;
	message = message.replace    ( /&/g, "&amp;"  ) ;


    var requestXML = "<vbrequest code='EMAIL_INVITES' pjuid='" + pjuid + "' name='" + name + "'  origin='" + origin + "' to=" + "'" + toEmailAddresses + "' "
	requestXML += " message='" + message + "' url='" + landingPageUrl + "' />";
	var url = DataServiceBackEnd.GAME_SERVER_URL;
      
	if ( DataServiceBackEnd.DUMMY_DATA ) {
		url = "./dummyData/RateQuestionOk.xml"; 
    }
	 
	/**
	* If in "game play in facebook" mode, we will need to put the "cross context" session id on the URL.
	*/
	url = appendWebAppSessionIdToUrlIfNecessary (url);
	 
    var expectedResponseCodes = [ "OK" ]

   clearDupResponseHandlingFlags ();
	callDataService ( requestXML, GenericResponse, url , callback, expectedResponseCodes );

}



/****************************************************************
*
* Data Services Infrastructure
*
*****************************************************************/

function buildRequestFromParms ( code, parms ) {
	
	var requestXML = "<vbrequest code='" + code + "' ";
	var p2 ;
	
	for ( var p in parms ) 
	{
		p2 = parms[p];
		requestXML += " " + p + "='" + p2  + "' ";
	}
	requestXML += " />";	
	
	return requestXML;
}

/*
	var requestXML = "<vbrequest code='RATE_QUESTION' ";
	
	var parms = new Object ();
	parms.questionId = questionId;
	parms.rating = rating;
	
	for ( var p in parms ) {
		requestXML += " " + p + "='" + parms[p]  + "' ";
	}
	requestXML += " />";

*/

function postDataToEndpoint ( requestData, endPointURL, callback ) {

//alert ( "CALL DATA SERVICE: " + requestXML + " endPointURL: " + endPointURL );

// alert ( " callDataService called, " + callback.extraData );

   var requestDataUrlEncoded = "";
   var numParmsProcessed = 0;
   for ( var p in requestData ) {
	   
	   if ( p == "toString" ) {
		   continue;
	   }
	   
	   if ( numParmsProcessed > 0 ) {
		   requestDataUrlEncoded += "&";
	   }
	   requestDataUrlEncoded += p + "=" + escape (requestData[p]);
	   numParmsProcessed++;
   }
   
   var ajaxCallParms = { 
      method: 'post',
	  
	  postBody:requestDataUrlEncoded,
	  
      onComplete: function ( originalRequest ) {
	 
		try {
	
	    //   alert ( "DONE IT!" );
//alert ( " TEXT: " + originalRequest.responseText );
//alert ( " originalRequest.responseXML: " + originalRequest.responseXML );
//alert ( " originalRequest.responseXML.firstChild: " + originalRequest.responseXML.firstChild );

			
			try {
				m_dataServiceTraceString += " REQ: " + requestData + "\r" + "\r";
			} catch ( exctrace ) {
			}
			
				
			// alert ( "GOT DATA" );
			
			//   var responseObject = new responseClass ();
			//   responseObject.parseXML (  originalRequest.responseXML.firstChild );
			   
			  
			// alert ( "CALL DATA SERVICE, callback.extraData: " ); //+ callback.extraData );
			  
			   callback ( originalRequest.responseText  );
			
		} catch ( exc ) {
		   alert ( "postDataToEndpoint Exception: " + exc + " m_debugStr: " + m_debugStr );
		}	

      } 
	};
				 
    myAjax = new Ajax.Request( endPointURL, ajaxCallParms );

}


function parseXmlStringIntoDocument ( xmlString ) {
	
	
   var xmlDoc=null;
	var parser = null;
	
   /**
   * IE
   */	
	try {
	   xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async="false";
      xmlDoc.loadXML(xmlString);
	
      //alert ( "IE xmlDoc: " + xmlDoc );
	} catch ( excNotIe ) {
      /**
      * Non-IE
      */
      parser=new DOMParser();
      xmlDoc=parser.parseFromString(xmlString,"text/xml");
		
		//alert ( "FF/other xmlDoc: " + xmlDoc );
	}
	
	return xmlDoc;

}

function removeWhiteSpaceNodes ( element ) {

alert ( "CALLED: removeWhiteSpaceNodes LEN: " + element.childNodes.length );
    for (var i = 0; i < element.childNodes.length; i++) {
      var node = element.childNodes[i];
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
		  alert ( "REMOVE ?" );
        Element.remove(node);
	  }
    }
alert ( "EXIT: removeWhiteSpaceNodes" );
}

function getFirstNonProcessingChild ( element ) {
	
	/**
	* ISSUE: This requires that the resonse from the back end is always in a "vbresponse" element.
	*/
	var rootNode = null;
	
	try {
		rootNode = element.getElementsByTagName('vbresponse')[0];
	} catch ( exhide ) {
	}
	
	//alert ( " rootNode: " + rootNode );
	
	return rootNode;
	
/*
	var firstChild = element.firstChild;
	
	// If not a processing instruction, this is it!
	if ( firstChild.nodeType != 7 ) {
		return firstChild;
	}
	
	var children =element.childNodes;
    for (i=0;i<children.length;i++) {
		var child = children[i];
		if ( child.nodeType != 7 ) {
			firstChild = child;
			break;
		}
	}
	
	return firstChild;
	*/
	
}

var m_singleDataServiceCallDebugString = null;
var m_responseTextForDebugging = null;

function callDataService ( requestXML, responseClass, endPointURL, callback, expectedResponseCodes ) {

   m_responseTextForDebugging = null;
   
//alert ( "CALL DATA SERVICE: " + requestXML + " endPointURL: " + endPointURL );

// alert ( " callDataService called, " + callback.extraData );

m_singleDataServiceCallDebugString = "REQ: " + requestXML;

m_dataServiceTraceString += " callDataService ENTRY requestXML: " + requestXML + "\r" + "\r";

   var ajaxCallParms = { 
      method: 'post',
	  
	  postBody:requestXML,
	  
      onComplete: function ( originalRequest ) {
	 
		try {
						
			m_singleDataServiceCallDebugString += " onComplete entry ";
			
			//m_watch_didCompleteAjaxCall = true;
			
			try {
			   if ( window.idOfWatchTimer != null ) {
				  clearTimeout (window.idOfWatchTimer);
				  window.idOfWatchTimer = null;
			   }
			} catch ( excWatcher ) {
				alert ( "EXC IN watcher" );
				var excString = "";
				for ( var p in excWatcher ) {
					excString += ( p + ":" + excWatcher[p] ) + " ";
				}
				alert ( "DETAILS: " + excString );
			}
	
//alert ( " TEXT: " + originalRequest.responseText );
//alert ( " originalRequest.responseXML: " + originalRequest.responseXML );
//alert ( " originalRequest.responseXML.firstChild: " + originalRequest.responseXML.firstChild );

             m_singleDataServiceCallDebugString += " getting generic response, response: " + originalRequest.responseText;
			
			var genericResponse = new GenericResponse ();
			var rootNode = null;
			var xmlDocument = null;
			if ( originalRequest.responseXML != null && originalRequest.responseXML.firstChild != null ) {
				xmlDocument = originalRequest.responseXML;
			} else {
				xmlDocument = parseXmlStringIntoDocument ( originalRequest.responseText );
			}
			var rootNode = getFirstNonProcessingChild (xmlDocument);
			//alert ( "NEW CODE!!!" );
			
			 //originalRequest.responseXML);
			//alert ( "USED STR" );
			
			
			m_singleDataServiceCallDebugString += " genericResponse: " + genericResponse;
			m_singleDataServiceCallDebugString += " originalRequest.responseXML: " + originalRequest.responseXML;
			m_singleDataServiceCallDebugString += " originalRequest.responseXML.rootNode: " + rootNode;
			//originalRequest.responseXML.firstChild;
						
			//removeWhiteSpaceNodes ( originalRequest.responseXML );
			
			try {
			   genericResponse.parseXML (  rootNode ); //originalRequest.responseXML.firstChild );
			} catch ( excParseGeneric ) {
	            m_singleDataServiceCallDebugString = "Data From Server [" + originalRequest.responseText + "] " + m_singleDataServiceCallDebugString;
                m_responseTextForDebugging = originalRequest.responseText;
//alert ( "ABOUT TO THROW" );
				throw "Xml Parsing Error - Click Details...";
			}
		
			
			m_singleDataServiceCallDebugString += " survived parse generic ";
			
			var isExpectedResponseCode = false;
			for ( var idx = 0; idx < expectedResponseCodes.length; idx++ ) {
				var expectedCode = expectedResponseCodes[idx];
				if ( genericResponse.code == expectedCode ) {
					isExpectedResponseCode = true;
					break;
				}
			}
			
/**
* SLW 9/22 process multiple responses back for a GET_QUESTION or ANSWER method.

	m_getQuestionCallOutstanding = true;
	m_getQuestionCallResponseReceived = false;
	
   m_getAnswerCallOutstanding = true;
   m_getAnswerCallResponseReceived = false;
	

*/
         if ( isExpectedResponseCode ) {
				
				if ( m_getQuestionCallOutstanding == true ) {
					if ( m_getQuestionCallResponseReceived == true ) {
					  // alert ( "DUP, DO NOT PROCESS GET QUESTION RESPONSE" );
					   return; 
					} else {
						m_getQuestionCallResponseReceived = true;
					}
				}

				if ( m_getAnswerCallOutstanding == true ) {
					if ( m_getAnswerCallResponseReceived == true ) {
					   //alert ( "DUP, DO NOT PROCESS ANSSER RESP" );
					   return; 
					} else {
						m_getAnswerCallResponseReceived = true;
					}
				}

			}
/**
* >>> END OF SLW 9/22 change.
*/
			
			try {
				m_dataServiceTraceString += " REQ: " + requestXML + "\r" + "\r";
				m_dataServiceTraceString += " RESP: " + originalRequest.responseText + "\r" + "\r";
			} catch ( exctrace ) {
			}
			
			if ( !isExpectedResponseCode ) {
				
			//alert ( "ERROR.  UNEXPECTED RESPONSE CODE: " + genericResponse.code + " MESSAGE: " + genericResponse.msg );
				
				//alert ( " originalRequest.responseText: "+ originalRequest.responseText );
				
				m_singleDataServiceCallDebugString = " orig req: " + requestXML + " " +  
				   " originalRequest.responseText: " + originalRequest.responseText + " " + m_singleDataServiceCallDebugString;
				
				var receivedCode = null;
				
				
				
				if ( genericResponse ) {
				   m_singleDataServiceCallDebugString = "UNEXPECTED CODE [ " + genericResponse.code + " ] EXPECTED: [ " +
						expectedResponseCodes + "] " + m_singleDataServiceCallDebugString;
				   
				   m_responseTextForDebugging = genericResponse.msg;
				   
				   receivedCode = "Unexpected Message (" + genericResponse.code + ")";
				   if ( genericResponse.code == null || genericResponse.code == "null" ) {
					   m_responseTextForDebugging = originalRequest.responseText;
					   receivedCode = "Invalid Response - Click Details...";
				   }
				}
				
				if ( m_doNotShowFatalErrorMessage == false ) {
	//alert ( "bad data: " + originalRequest.responseText );	
	               m_singleDataServiceCallDebugString = "Data From Server [" + originalRequest.responseText + "] " + m_singleDataServiceCallDebugString;
				  // m_responseTextForDebugging = originalRequest.responseText;
				   showFatalGameErrorDialog ( m_singleDataServiceCallDebugString, receivedCode, m_responseTextForDebugging ); 
				} else {
				  // If EndGame, don't put up error. Could end up in an endless loop of errors/dialog/errors/dialog/etc.	alert ( "SUPRESSED" );
				}
				
				//originalRequest.responseText ); //m_singleDataServiceCallDebugString +  m_dataServiceTraceString );
				
			} else {
			
	// alert ( "GOT DATA" );
			
			  m_singleDataServiceCallDebugString += " now trying to parse with class "; //: " + responseClass );
			
			   var responseObject = new responseClass ();
			   
			   try {
				   
//	alert ( "ABOUT TO PARSE" );			   
			      responseObject.parseXML ( rootNode ); //originalRequest.responseXML.firstChild );
				  
	//alert ( "SURVIVED PARSE" );			  
			   } catch ( excParse ) {
	//alert ( "ABOUT DO SO SOMETHING" );			   
	               m_singleDataServiceCallDebugString = "Data From Server [" + originalRequest.responseText + "] " + m_singleDataServiceCallDebugString;
				  // m_responseTextForDebugging = originalRequest.responseText;
	//alert ( "bad data: " + originalRequest.responseText );	
				   throw "Xml Parsing Error - Click Details...";
			   }
			  
			// alert ( "CALL DATA SERVICE, callback.extraData: " ); //+ callback.extraData );
			  
	//alert ( "MAKING CALLBACK CALL" );
	
			   m_singleDataServiceCallDebugString += " now making callback call ";
			   
			   callback ( responseObject, originalRequest.responseText , callback.extraData );
			   
//alert ( " callback: " + callback );

			}
		} catch ( exc ) {
		  
		  
//alert ( " EXCEPTION: " + exc );


				m_singleDataServiceCallDebugString = " orig req: " + requestXML + " " +  
				   " originalRequest.responseText: " + originalRequest.responseText + " " + m_singleDataServiceCallDebugString;
				   
				m_singleDataServiceCallDebugString = "EXCEPTION[" + exc + "]" + m_singleDataServiceCallDebugString;
				
				if ( m_doNotShowFatalErrorMessage == false ) {
				   showFatalGameErrorDialog ( m_singleDataServiceCallDebugString, "(" + exc + ")", m_responseTextForDebugging );
				} else {
				   // If EndGame, don't put up error. Could end up in an endless loop of errors/dialog/errors/dialog/etc. alert ( "SUPRESSED" );
				}
				//originalRequest.responseText ); //m_singleDataServiceCallDebugString +  m_dataServiceTraceString );
		  
		  /*
		  alert ( "callDataService Exception: " + exc  + " m_singleDataServiceCallDebugString: " + m_singleDataServiceCallDebugString );
		   
		        showFatalGameErrorDialog ();
		   

				var excString = "";
				for ( var p in exc ) {
					excString += ( p + ":" + exc[p] ) + " ";
				}
				alert ( "DETAILS: " + excString );
			*/

		  // setTimeout ( sendErrorReportToPopjax, 10 );
		   //alert ( "REQ: " + requestXML );
		   //alert ( "RESP: " + originalRequest.responseText );
		}	

      } 
	};
				 
	//m_watch_didCompleteAjaxCall = false;			 
m_dataServiceTraceString += "call Ajax.Request () " + "\r" + "\r";				 
    myAjax = new Ajax.Request( endPointURL, ajaxCallParms );
m_dataServiceTraceString += "survived call Ajax.Request () " + "\r" + "\r";		

}


function callDataServiceMultiResponseClasses ( requestXML, responseClasses, endPointURL, callback, expectedResponseCodes ) {

   m_responseTextForDebugging = null;
   
// alert ( " callDataService called, " + callback.extraData );

   var ajaxCallParms = { 
      method: 'post',
	  
	  postBody:requestXML,
	  
      onComplete: function ( originalRequest ) {
	 
		try {
	
	        //alert ( " response text: " + originalRequest.responseText );
			//alert ( "  originalRequest.responseXML.firstChild: " +  originalRequest.responseXML.firstChild );
			//alert ( " NODE TYPE: " + originalRequest.responseXML.firstChild.nodeType );
			
	       // removeWhiteSpaceNodes ( originalRequest.responseXML );
			
			//var firstChild = getFirstNonProcessingChild (originalRequest.responseXML);
			//alert ( "FIRST CHILD: " + firstChild );
			
			var genericResponse = new GenericResponse ();
			
			var rootNode = null;
			var xmlDocument = null;
			//alert ( "MULTI" );
			if ( originalRequest.responseXML != null && originalRequest.responseXML.firstChild != null ) {
				xmlDocument = originalRequest.responseXML;
			} else {
				xmlDocument = parseXmlStringIntoDocument ( originalRequest.responseText );
			}
			var rootNode = getFirstNonProcessingChild (xmlDocument);
			
			
			try {
			   genericResponse.parseXML ( rootNode ); //originalRequest.responseXML.firstChild );
			} catch ( excParseGeneric ) {
	           m_singleDataServiceCallDebugString = "Data From Server [" + originalRequest.responseText + "] " + m_singleDataServiceCallDebugString;
			   m_responseTextForDebugging = originalRequest.responseText;
				
				throw "Xml Parsing Error 1 - Click Details...";
			}
			
			//genericResponse.parseXML ( getFirstNonProcessingChild (originalRequest.responseXML) ); //originalRequest.responseXML.firstChild );
			var isExpectedResponseCode = false;
			for ( var idx = 0; idx < expectedResponseCodes.length; idx++ ) {
				var expectedCode = expectedResponseCodes[idx];
				if ( genericResponse.code == expectedCode ) {
					isExpectedResponseCode = true;
					break;
				}
			}

			try {
				m_dataServiceTraceString += " REQ: " + requestXML + "\r" + "\r";
				m_dataServiceTraceString += " RESP: " + originalRequest.responseText + "\r" + "\r";
			} catch ( exctrace ) {
			}

			if ( !isExpectedResponseCode ) {
				//alert ( "ERROR.  CODE: " + genericResponse.code + " MESSAGE: " + genericResponse.msg );
		
				m_singleDataServiceCallDebugString = " orig req: " + requestXML + " " +  
				   " originalRequest.responseText: " + originalRequest.responseText + " " + m_singleDataServiceCallDebugString;
				
				var receivedCode = null;
				
				if ( genericResponse ) {
				   m_singleDataServiceCallDebugString = "UNEXPECTED CODE [ " + genericResponse.code + " ] EXPECTED: [ " +
						expectedResponseCodes + "] " + m_singleDataServiceCallDebugString;
				   
				   receivedCode = "Unexpected Message (" + genericResponse.code + ")";
				   
				   m_responseTextForDebugging = genericResponse.msg;
				   
				   if ( genericResponse.code == null || genericResponse.code == "null" ) {
					   
	                   m_singleDataServiceCallDebugString = 
					      "Data From Server [" + originalRequest.responseText + "] " + m_singleDataServiceCallDebugString;
			           m_responseTextForDebugging = originalRequest.responseText;
					   
					   receivedCode = "Invalid Response - Click Details...";
				   } 				   
				}
				
				showFatalGameErrorDialog ( m_singleDataServiceCallDebugString, receivedCode, m_responseTextForDebugging ); //originalRequest.responseText ); //m_singleDataServiceCallDebugString +  		
				
			} else {
			
			// alert ( "GOT DATA" );
			
			  // alert ( "ABOUT TO REMOVE SPACE" );
			  // removeWhiteSpaceNodes ( originalRequest.responseXML );
			   
			   var responseClass = responseClasses[genericResponse.code];
			   var responseObject = new responseClass ();
			   
			   try {
			      responseObject.parseXML ( rootNode ); //originalRequest.responseXML.firstChild );
			   } catch ( excParse ) {
				   
				   m_singleDataServiceCallDebugString = 
					  "Data From Server [" + originalRequest.responseText + "] " + m_singleDataServiceCallDebugString;
				  // m_responseTextForDebugging = originalRequest.responseText;
				   
				   throw "Xml Parsing Error - Click Details...";
			   }

			  
			// alert ( "CALL DATA SERVICE, callback.extraData: " ); //+ callback.extraData );
			  
//alert ( " callback: " + callback );

			   callback ( responseObject, originalRequest.responseText , callback.extraData );
			}
		} catch ( exc ) {
			
		  // alert ( "callDataServiceMultiResponseClasses Exception: " + exc );

				m_singleDataServiceCallDebugString = " orig req: " + requestXML + " " +  
				   " originalRequest.responseText: " + originalRequest.responseText + " " + m_singleDataServiceCallDebugString;
				   
				m_singleDataServiceCallDebugString = "EXCEPTION[" + exc + "]" + m_singleDataServiceCallDebugString;
				
				showFatalGameErrorDialog ( m_singleDataServiceCallDebugString,  "(" + exc + ")", m_responseTextForDebugging ); //originalRequest.responseText ); //m_singleDataServiceCallDebugString +  

		   //setTimeout ( sendErrorReportToPopjax, 10 );
		}	

      } 
	};
				 
    myAjax = new Ajax.Request( endPointURL, ajaxCallParms );

}

//alert ( "END LOAD DATA SERVICES" );


