/*
##############################################################
# Author:	Eric Mitchell
# Date:	09/2008
# Copyright VHPS 2008
# Purpose:	Wrapper for AJAX Utilities (Implements YUI YAHOO.util.Connect Framework)
##############################################################
*/

//Instantiate base VHPS Object
if(!VHPS){
	var VHPS = new Object();
}

//Instantiate base VHPS.Ajax Object
if(!VHPS.Ajax){
	VHPS.Ajax = new Object();
}


//VHPS.Ajax.EasyJSONRequest is a wrapper that makes use of VHPS.Ajax.ContentLoader below
//This implementation relies on the core code /ajaxController provides for making ajax calls that return JSON.
VHPS.Ajax.EasyJSONRequest = function(baseObj, requestParamObj){
	this.baseObj = baseObj;
	this.requestParamObj = requestParamObj || {};
	this.ajaxRequestObj = {
			url: '/ajaxController/index.cfm',
			method: 'POST'
		}
	this.ajaxHelper = new VHPS.Ajax.ContentLoader(this, this.ajaxRequestObj, this.requestParamObj);
	return this.ajaxHelper;
}
VHPS.Ajax.EasyJSONRequest.prototype = {
	ajaxUpdate:  function(responseData) {
			//**NOTE that Structure's keys will always come back UPPERCASE if jsonencode was used on the server..
			try{
				var aR = eval('(' + responseData + ')');	
			}catch(er){
				//$TODO: add real error handling
				alert('Error with JSON Evaluation');
				/*	var ask = confirm("Would you like to see the JSON string data that was passed?");
				if(ask){
					new VHPS.Ajax.ErrorDisplay(7, responseData);
				}*/
			}
			if(aR.RETURNMETHOD){
				//if we find a "returnmethod" in the json obj, call it passing the whole json obj.
				//TODO: test to see if the passed return method is actually part of the calling object.
				eval('this.baseObj.' + aR.RETURNMETHOD +'(aR)');
			}else{
				//$TODO: add real error handling
				alert('No return method was passed from the server');
			}
		},
		
		ajaxCustomErrorhandler: function(func, errNum, errMsg){
			//calls the "func" on the baseObj to pass off the error
			eval('this.baseObj.' + func +'(errNum,errMsg)');
		},
	
		ajaxErrorHandler: function(error, http, errNum){
			//Easy JSON Request doesn't make use of this function. 
			//if you want to handle errors, use the ajaxCustomErrorhandler
			return false;
		}
}



//ContentLoader: Wrapper object for making XMLHTTP requests via DOJO toolkit
/*NOTE: "callerObj" must have a ajaxUpdate method that accepts the return data 
   		that is returned from the server*/
VHPS.Ajax.ContentLoader = function(callerObj, ajaxRequestObj, queryStringObj ) {
   this.callerObj     		= callerObj;
   this.url           		= ajaxRequestObj.url || '';
   this.changeURL				= ajaxRequestObj.changeURL || ''; //not currently implemented
   this.queryStringObj 		= queryStringObj || {};
   this.allowSend			= true;
   if(this.url == ''){
   		alert('AJAX URL is null');
		this.allowSend = false;
   }

}

VHPS.Ajax.ContentLoader.prototype = {
//sendRequest: responsible for sending request to dojo
	sendRequest: function(argsObj) {	
		var _this = this;
		/*var finalArgsObj = {
			url: oThis.url,
		   load: oThis.handleAjaxSuccess,
			error: oThis.handleAjaxFailure,
		   mimetype: "text/plain",
			changeURL: oThis.changeURL,
			method: oThis.method, 
			postContent:  oThis.buildPostContent(argsObj),
			theCallerObj : oThis.callerObj,
			callSpecificErrorHandler :oThis.getCallSpecificErrorHandler(argsObj)
		}*/
		//alert('sending:' + this.component);
		if(this.allowSend){
			//dojo.io.bind(finalArgsObj);
			
			
			this.callback = {
				success:_this.handleAjaxSuccess,
				failure:_this.handleAjaxFailure,
				argument: {'theCallerObj':_this.callerObj,'callSpecificErrorHandler':_this.getCallSpecificErrorHandler(argsObj)}
			}
			
			YAHOO.util.Connect.asyncRequest('POST', _this.url, this.callback, _this.buildPostContent(argsObj));
			
			
		}else{
			alert('Ajax config error...can\'t send');
		}
	},
	
	//for a given request, this looks for a custom error handler method the developer wants called
	getCallSpecificErrorHandler: function(argsObj){
		var err;
		for(param in argsObj){
			//test to see if a custom error handler was passed in the args for this specific request.
			if(param.toUpperCase() == 'ERRORHANDLER'){
				return argsObj[param];
				break;
			}
		}
	},
	
//buildPostContent: combines any contentloader specific arguments with passed arguments for use in postContent property
	buildPostContent: function(argsObj){
		//$TODO: should escape any "&" symbols in this prior to building a string (verify)
		var postContent = '';
		for(param in this.queryStringObj){
			postContent += '&'+param+'='+this.queryStringObj[param];
		}
		for(param in argsObj){
			postContent += '&'+param+'='+argsObj[param];
		}
		return postContent.substring(1, postContent.length);
	},
	
//handleAjaxSuccess: listener function receives server data for successful AJAX responses
	handleAjaxSuccess: function(o) {
		//$TODO: verify that this method exists before calling it
		if(o.argument.theCallerObj.ajaxUpdate){
			o.argument.theCallerObj.ajaxUpdate(o.responseText);	
		}else{
			alert('your object needs an ajaxUpdate method');
		}
 	 },
	 
//handleAjaxFailure: listener function receives server error for failed AJAX responses
	handleAjaxFailure: function(o) {
	
		errNum = parseInt(o.status);
		var handled = false;
		
		//see if there is a callSpecificErrorHandler defined for this request if the errorNum is between 600 and 700
		//if there was a custom error handler and the error code was between 600 and 700 we assume the 
		//developer has handled it with their own function.
		if(errNum <= 700 && errNum >= 600){
			if(o.argument.theCallerObj.ajaxCustomErrorhandler && o.argument.callSpecificErrorHandler){
				o.argument.theCallerObj.ajaxCustomErrorhandler(o.argument.callSpecificErrorHandler, errNum, o.responseText);
				handled = true;
			}
		}else{
			//errNum is not 600 to 700
			if(!handled){
				//see if the developer has an error handler for this error
				if(o.argument.theCallerObj.ajaxErrorHandler){
					handled = o.argument.theCallerObj.ajaxErrorHandler(o, null, errNum);	
				}
			}
			if(!handled){
				//if developer didn't handle the error, let our default error handler fire
				var handleError = new VHPS.Ajax.AjaxErrorHandler(o.responseText, null, errNum);
			}
	 	 }
		}
}

//AjaxErrorHandler: directs traffic based on http error codes
VHPS.Ajax.AjaxErrorHandler = function(strError, objHttp, errNum) {
	this.strError = strError;
	this.errNum = errNum;
	switch(this.errNum){
			case 555:
				//Input's built in session timeout code
				new VHPS.Ajax.ErrorDisplay(1);
				break;
			case 556:
				new VHPS.Ajax.ErrorDisplay(3);
				break;
			case 404:
				//File Not Found
				new VHPS.Ajax.ErrorDisplay(2);
				break;
			case 405:
				//Method not Allowed
				new VHPS.Ajax.ErrorDisplay(4);
				break;
			case 500:
				//Server (ColdFusion) error
				new VHPS.Ajax.ErrorDisplay(2);
				break;
			case 501:
				//Server (ColdFusion) error with debug on... for developers
				new VHPS.Ajax.ErrorDisplay(5, this.strError);
				break;
			case 701:
				//developer debug dump
				new VHPS.Ajax.ErrorDisplay(6, this.strError);
				break;
			default:
				//something bad happened
				new VHPS.Ajax.ErrorDisplay(2);
				break;
		}
}

//ErrorDisplay: Builds a centered div with appropriate error message and hides all forms on the page
VHPS.Ajax.ErrorDisplay = function(errId, message){
	this.message = message;
	if(!document.getElementById("ajaxErrorDiv")){
		tmpDiv = document.createElement("div");
		tmpDiv.id = "ajaxErrorDiv";
		tmpDiv.style.position = 'absolute';
		tmpDiv.style.zIndex = 1000;
		tmpDiv.style.background = '#eaeaea';
		tmpDiv.style.padding = '8px';
		tmpDiv.style.border = 'black solid 2px';
		document.body.appendChild(tmpDiv);	
	}
	this.oErrorDiv = document.getElementById("ajaxErrorDiv");
	appForms = document.getElementsByTagName("form"); 
	for(var i=0;i<appForms.length;i++){
		appForms[i].style.visibility = 'hidden';
	}
	this.oErrorDiv.innerHTML = this.getErrorMsg(errId);
	this.w = 400;
	this.h = 150;
	this.centerError();	
}

VHPS.Ajax.ErrorDisplay.prototype = {
//centerError: places div center on user's browser
	centerError: function() {	
		if(window.innerWidth){
			var xc=Math.round((window.innerWidth/2)-(this.w/2))
			var yc=Math.round((window.innerHeight/2)-(this.h/2))
		}else if(document.body.clientWidth){
			var xc=Math.round((document.body.clientWidth/2)-(this.w/2))
			var yc=Math.round((document.body.clientHeight/2)-(this.h/2))
		}else{
			//just ballpark it
			var xc = 200;
			var yc = 200;
		}
		if(this.oErrorDiv.moveTo){
			this.oErrorDiv.style.moveTo(xc,yc);
		}else{
			this.oErrorDiv.style.left = xc + "px";
			this.oErrorDiv.style.top = yc + "px";
		}
	},
	
//getErrorMsg: based on error Id, returns error message to display in error div.  These should be generic error and never application specific
//if an application specific error message is needed, the developer should throw a 550 http error and implement their own ajaxErrorHandler
	getErrorMsg: function(errId){
		//return 'There was an error: ID ' + errId;
switch(parseInt(errId)){
			case 1:
				//Session Timeout message
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>Your Session Has Timed Out.</b></font><br>';
 				errMsg += '<br>Please click the refresh button on your browser or Click '; 
				errMsg += '<a href="/index.cfm" target="_top">here</a> to return to the VHPS home page.<br>Thank you.'; 
				errMsg += '<br><br></td></tr></table>';
				break;
			case 2:
				//Misc Server Error
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>We\'re sorry, an error has occurred.</b></font><br>';
 				errMsg += '<br>This error has been logged and will be investigated in a timely manner by VHPS technical staff.'; 
				errMsg += ' If you have further questions, please contact ';
				errMsg += '<a href="mailto:memberservices@input.com">memberservices@input.com</a>. Thank you.';
				errMsg += '<br><br>Click <a href="/index.cfm" target="_top">here</a> to return to the VHPS home page.</td></tr></table>';
				break;
			case 3:
				//Likely trying to hit ajax app without going through the front end application (not sure this will ever happen)
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>The Content You Requested ';
				errMsg += 'Isn\'t Available</b></font><br><br>';
 				errMsg += 'Please click the refresh button on your browser or Click '; 
				errMsg += '<a href="/index.cfm" target="_top">here</a> to return to the VHPS home page.<br>Thank you.'; 
				errMsg += '<br><br></td></tr></table>';
				break;
			case 4:
				//This error can be thrown from dojo when the path to the ajax file isn't correctly specified... possibly other scenarios as well)
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>A 405 error occured during an AJAX call ';
				errMsg += '</b></font><br><br>';
 				errMsg += 'Verify that the path to the AJAX resource is correct.'; 
				errMsg += '<br><br>Click <a href="/index.cfm" target="_top">here</a> to return to the VHPS home page.</td></tr></table>'; 
				break;
			case 5:
				//ColdFusion error for developers... debug mode
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>An error was thrown during an AJAX call ';
				errMsg += '</b></font><br><br>';
 				//print the message and remove the generic portion
 				errMsg += this.message.replace(/^XMLHttpTransport Error: [0-9]+ /, ''); 
				errMsg += '<br><br>Click <a href="/index.cfm" target="_top">here</a> to return to the VHPS home page.</td></tr></table>'; 
				break;
			case 6:
				//debug dump for developers
				var errMsg ='<table width="350" height="150" align="center"><tr><td  CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>Ajax Debug Dump';
				errMsg += '</b></font><br><br>';
				//print the message and remove the generic portion
 				errMsg += this.message.replace(/^XMLHttpTransport Error: [0-9]+ /, ''); 
				errMsg += '<br><br></td></tr></table>'; 
				break;
			case 7:
				//JSON dump for developers
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>Ajax JSON Dump';
				errMsg += '</b></font><br><br>';
				//print the JSON string
 				errMsg += this.message; 
				errMsg += '<br><br></td></tr></table>'; 
				break;
			default:
				//catch all error
				var errMsg ='<table width="350" height="150" align="center"><tr><td width="100%" CLASS="MAINVHPS" valign="top">';
 				errMsg += '<font size="3" face="arial" color="550000"><b>We\'re sorry, an error has occurred.</b></font><br>';
 				errMsg += '<br>This error has been logged and will be investigated in a timely manner by VHPS technical staff.'; 
				errMsg += 'If you have further questions, please contact';
				errMsg += '<a href="mailto:memberservices@input.com">memberservices@input.com</a>. Thank you.';
				errMsg += '<br><br>Click <a href="/index.cfm" target="_top">here</a> to return to the VHPS home page.</td></tr></table>';
				break;
		}
		return errMsg;
	}
}