/**
 * P.I.C.S. JS Framework 5.0.0 - ajax extension
 * Copyright(c) 2009 P.I.C.S. EDV GmbH
 * http://www.pics.co.at
 * 
 * @author Ing. Christian Grösswang
 * 
 * 20100317,gc - v5.00.00		rework of pics.Ajax 1.01
 * 20100506,gc - v5.00.01		add PJR ( pics-json-return ) as interal callback
 * 20100512,gc - v5.00.02		small bugfixes in ajax/json-routines
 */

/**
 * @class pics.Ajax
 * function for ajax-loading
 * @singleton
 */
pics.Ajax = {
    		version 	: '5.0.0'			//* @type String	version of the framework
    		,requests	: new Array()		//* @type Array		list of current requests
    		,debug		: false				//* @type Bool		enable debugging
    		,debuglog	: ''				//* @type String	debuglog
		};	// pics.ajax
			
		

	/**
	 * pics.Ajax.request()
	 *		start an ajax-request
     * 		@param 	{String} 	pUrl 			url to call
     * 		@param 	{String} 	pCallback 		callback-handler, see pics.Ajax.callBack for internal handlers
     * 		@param 	{String} 	pMethod 		GET/POST (default=GET)
     * 		@param 	{String} 	pPostParams 	params for post
     * 		@param 	{Mixed} 	pExtraParam 	additional parameter stored in the request-array
 	 *		@return	{Int}		id of the entry in the requests-array
	 */
	pics.Ajax.request = function(pUrl, pCallback, pMethod, pPostParams, pExtraParam)
	{
		// check params
		if (pics.isUndefined(pUrl)) 		return false;
		if (pics.isUndefined(pCallback)) 	return false;
		if (pics.isUndefined(pMethod)) 		pMethod='GET';
		if (pics.isUndefined(pPostParams)) 	pPostParams='';
		if (pics.isUndefined(pExtraParam)) 	pExtraParam='';

		// find the next position in the erry
		var lID=pics.Ajax.requests.length;
		pics.Ajax.requests[lID]=new Array();
		// add params
		pics.Ajax.requests[lID]["url"]		= pUrl;
		pics.Ajax.requests[lID]["method"]	= pMethod;
		pics.Ajax.requests[lID]["callback"]	= pCallback;
		pics.Ajax.requests[lID]["params"]	= pPostParams;
		pics.Ajax.requests[lID]["extra"]	= pExtraParam;
		pics.Ajax.requests[lID]["state"]	= 0;
		pics.Ajax.requests[lID]["result"]	= '';
		pics.Ajax.requests[lID]["timestamp"]= new Date();

		if (pics.Ajax.debug) pics.Ajax.debuglog+='pics.ajax.request('+lID+') '+pUrl+'\n';
		
		// add a timestamp to the url to prevent caching
		pUrl+=(pUrl.indexOf('?')==-1 ? '?' : '&')+'picsts='+pics.Ajax.requests[lID]["timestamp"].getTime();
		
		// create the object
		pics.Ajax.requests[lID]["object"]=pics.Ajax.createXMLHttpRequestObject();
		
		// and start the request (async)	
		pics.Ajax.requests[lID]["object"].open(pMethod,pUrl,true);
		
		// set the callback-handler
		pics.Ajax.requests[lID]["object"].onreadystatechange=pics.Ajax.callBack(lID);
		
		var lSendParam=null;
		if (pMethod=="POST") // if method is POST 
		{
			// Header definieren
			pics.Ajax.requests[lID]["object"].setRequestHeader("Content-Type","application/x-www-form-urlencoded");
			if (pPostParams!='')  lSendParam=pPostParams;
		}
		pics.Ajax.requests[lID]["object"].send(lSendParam);
	}; // pics.Ajax.request

	
	/**
	 * pics.Ajax.request_sync()
	 *		synchronen Request absetzen 
     * 		@param 	{String} 	pUrl 			url to call
     * 		@param 	{String} 	pMethod 		GET/POST (default=GET)
     * 		@param 	{String} 	pPostParams 	params for post
 	 *		@return	{String}	result of the request
	 */
	pics.Ajax.request_sync = function(pUrl, pMethod, pPostParams)
	{
		// check params
		if (pics.isUndefined(pUrl)) 		return false;
		if (pics.isUndefined(pMethod)) 		pMethod='GET';
		if (pics.isUndefined(pPostParams)) 	pPostParams='';

		// find the next position in the erry
		var lID=pics.Ajax.requests.length;
		pics.Ajax.requests[lID]=new Array();
		// add params
		pics.Ajax.requests[lID]["url"]		= pUrl;
		pics.Ajax.requests[lID]["method"]	= pMethod;
		pics.Ajax.requests[lID]["callback"]	= '*SYNC';
		pics.Ajax.requests[lID]["params"]	= pPostParams;
		pics.Ajax.requests[lID]["state"]	= 0;
		pics.Ajax.requests[lID]["result"]	= '';
		pics.Ajax.requests[lID]["timestamp"]= new Date();


		if (pics.Ajax.debug) pics.Ajax.debuglog+='pics.ajax.request_sync('+lID+') '+pUrl+'\n';
		
		// add a timestamp to the url to prevent caching
		pUrl+=(pUrl.indexOf('?')==-1 ? '?' : '&')+'picsts='+pics.Ajax.requests[lID]["timestamp"].getTime();
		
		// create the object
		pics.Ajax.requests[lID]["object"]=pics.Ajax.createXMLHttpRequestObject();
		
		// and start the request (async)	
		pics.Ajax.requests[lID]["object"].open(pMethod,pUrl,false);
		
		// set the callback-handler
		pics.Ajax.requests[lID]["object"].onreadystatechange=pics.Ajax.callBack(lID);
		
		var lSendParam=null;
		if (pMethod=="POST") // if method is POST 
		{
			// Header definieren
			pics.Ajax.requests[lID]["object"].setRequestHeader("Content-Type","application/x-www-form-urlencoded");
			if (pPostParams!='')  lSendParam=pPostParams;
		}
		pics.Ajax.requests[lID]["object"].send(lSendParam);

		// check the result
		pics.Ajax.requests[lID]["state"]	= pics.Ajax.requests[lID]["object"].readyState;
		pics.Ajax.requests[lID]["result"]	= pics.Ajax.requests[lID]["object"].status;
		if (pics.Ajax.requests[lID]["result"] == 200) 
		{
			pics.Ajax.requests[lID]["result"] = pics.Ajax.requests[lID]["object"].responseText;
		}
		// destroy the object
		pics.Ajax.requests[lID]["object"]=null;
		return pics.Ajax.requests[lID]["result"];
	}; // pics.Ajax.request_sync
	
	
	/**
	 * pics.Ajax.getResult()
	 *		get the result of the given request
     * 		@param 	{Int} 		pID 	id of the request in the queue
 	 *		@return	{String}	result of the request
	 */
	pics.Ajax.getResult = function(pID)
	{
		if (!pics.Ajax.requests[pID]["result"]) 	return "";
		return pics.Ajax.requests[pID]["result"];
	}; // pics.Ajax.getResult
	
	
	/**
	 * pics.Ajax.createXMLHttpRequestObject()
	 *		create a new XML/HTTP-Object
 	 *		@return	{Mixed}		XML/HTTP-object or false
	 */
	pics.Ajax.createXMLHttpRequestObject = function()
	{
		var oRequest=false;
	    // does the browser support the XMLHttpRequest-Object from Apple?
	    if (window.XMLHttpRequest) 
		{
	    	try 			{ oRequest = new XMLHttpRequest(); } 
			catch(error) 	{ oRequest = false; }
	    } // does the browser support the MS Windows Internet Explorer ActiveX-Version
 		else if(window.ActiveXObject) 
		{
	       	try				{ oRequest = new ActiveXObject("Msxml2.XMLHTTP"); } 
			catch(error) 
			{  
				try 			{ oRequest = new ActiveXObject("Microsoft.XMLHTTP"); } 
				catch(error) 	{ oRequest = false; }
			}
	    }
		if (!oRequest) 		alert("ACHTUNG Browser-Update erforderlich!\n\nIhr Browser unterstützt keine XMLHttp-Objekte.\nBitte verwenden Sie einen der folgenden Browser:\n\n - Internet Explorer ab Version 5.0\n - Mozilla ab Version 1.7.8\n - Firefox ab Version 1.0.2\n - Opera ab Version 8.0\n - Safari ab Version 1.2\n - Netscape ab Version 6.0\n\nVielen Dank für Ihr Verständnis!");
		
		// return
		return oRequest;		
	}; // pics.Ajax.createXMLHttpRequestObject


	/**
	 * pics.Ajax.callBack(pId)
	 *		callBack-handler for Ajax
	 *		there are the following special internal handlers:
	 *		*SILENT					silent request, no callback
	 *		*HTML:[ElementID]		add the result as innerHtml to the element with the given id
	 *		*HTML:EXTRA				add the result as innerHtml to the element given in the extra-param
	 *		*OPTION:[ElementID]		add the result as option-tags to the element with the given id
	 *		*ALERT					create an alert with the result
	 *		*MSGBOX:[Delay]			create a pics.gui.msgbox with the result			
     * 		@param 	{Int} 		pID 	id of the request in the queue
 	 *		@return	{Bool}		true
	 */
	pics.Ajax.callBack = function(pID)
	{
		return function () 
		{
			if (pics.isUndefined(pics.Ajax.requests[pID]["object"]))
			{
				alert("request "+pID+" not found!");
				return false;
			}
			pics.Ajax.requests[pID]["state"]	=	pics.Ajax.requests[pID]["object"].readyState;
			if (pics.Ajax.debug) 	pics.Ajax.debuglog+='pics.Ajax.callBack('+pID+') state: '+pics.Ajax.requests[pID]["state"]+'\n';
	
			// 0: initialized, 1: loading 2: load finished, 3: interaction, 4: ready
			if (pics.Ajax.requests[pID]["state"] == 4)
			{
				pics.Ajax.requests[pID]["result"]=pics.Ajax.requests[pID]["object"].status;
				if (pics.Ajax.debug) 	pics.Ajax.debuglog+='pics.Ajax.callBack('+pID+') status: '+pics.Ajax.requests[pID]["result"]+'\n';
	
				if (pics.Ajax.requests[pID]["result"] == 200) 
				{
					// load successful, save the result
					pics.Ajax.requests[pID]["result"] = pics.Ajax.requests[pID]["object"].responseText;
					// now call the given callback
					switch(pics.Ajax.requests[pID]["callback"].substr(0,5))
					{
						case "*SILE":		// SILENT = silent request, no callback
						case "*SYNC":		// SYNC   = synchron request, no callback needed
							break;
						case "*HTML":		// internal HTML-Callback-Handler setHTML
							pics.Ajax.setHTML(pID);
							break;
						case "*OPTI":		// internal OPTION-Tag-Callback-Handler setOPTION
							pics.Ajax.setOPTION(pID);
							break;
						case "*ALER":		// internal Callback-Handler alert
							alert(pics.Ajax.requests[pID]["result"]);
							break;
						case "*MSGB":		// Interner Callback-Handler msgbox
							var lTime=pics.Ajax.requests[pID]["callback"].substr(8);
							if (lTime=='') lTime=0;
							pics.gui.msgBox(pics.Ajax.requests[pID]["result"], true, true, lTime);
							break;
						case "*PJR:":		// internal Callback-Handler in pics-json-return-format
							var oJson=pics.JSON.loadFinished(pics.Ajax.requests[pID]["result"], pics.Ajax.requests[pID]["callback"].substr(5), pics.Ajax.requests[pID]["extra"]);
							break;
						case "*PJR-OLD:":		// internal Callback-Handler in pics-json-return-format
							try {
								var aReturn=pics.decodeJSON(pics.Ajax.requests[pID]["result"]);
							} // try
							catch(e)
							{
								var aReturn=new Array();
								pics.gui.msgBox("<b>save error</b><br>"+e, true, true);
							}
							var oForm=pics.Ajax.requests[pID]["extra"];
							var lStatus=false;
							for (var lType in aReturn)
							{
								switch(lType)
								{
									case "success":				// check the success of the save
										lStatus=aReturn[lType];
										break;
									case "msg":					// return message
										alert(aReturn[lType], true, true);
										// pics.gui.msgBox(aReturn[lType], true, true);
										break;
									case "html":				// html-content
										var lElement=pics.Ajax.requests[pID]["callback"].substr(5);
										pics.setHTML(lElement,aReturn[lType]);
										break;
									case "data":				// fields and values must be set 
										if (lStatus==true)
										{
											// walk through all the fields
											for (var lVar in aReturn[lType])
											{
												var lValue = aReturn[lType][lVar];
												// is it a single field or a array of fields
												if (pics.isArray(lValue))
												{
													// array => get the fields
													var aField=pics.findByName(oForm, lVar, false);
													for (var j=0;j<aFields.length;j++)
													{
														aFields[j].value=lValue[j];
													} // for
												} // if
												else
												{
													// single field - get the field
													var oField=pics.findByName(oForm, lVar, true);
													oField.value=lValue;
													// oForm.elements[lVar].value=lValue;
												} // else
											} // for
											
										}
										if (lStatus==true) 
										{
											// execute the javascripts
											for (var i=0;i<aJavascript.length;i++)
											{
												eval(aJavascript[i]);
											}				
											// hide the infobox
											oSaveInfo.hide();
										}
										
										
										break;
									case "js":			// execute the javascript after loading, format is JS: command 
											aJavascript=aReturn[lType];
										break;
								} // switch
							} // for

							break;

						default:			// individual function
							var lCallback=pics.Ajax.requests[pID]["callback"];
//							alert(pics.isFunction(lCallback));
							 if (pics.isFunction(lCallback))
							 {
							 	lCallback(pics.Ajax.getResult(pID),pID);
							 }
							 else
							 {
								eval(pics.Ajax.requests[pID]["callback"]+"(pics.Ajax.getResult("+pID+"),"+pID+")");
							 }
							break;
					} // switch
				} // if
				else 
				{
					alert("Es ist ein interner Fehler bei Request ("+pID+") aufgetreten:\n" + pics.Ajax.requests[pID]["object"].statusText);
					// alert(pics.Ajax.debuglog);
				} // else

				// destroy the object
				// pics.Ajax.requests[pID]["object"]=null
			} // if state
		}; // return function
	}; // pics.Ajax.callBack(pId)
	
	/**
	 * pics.Ajax.setHTML(pID)
	 *		internal setHTML-CallBack-handler
	 *		add the result as innerHTML for element with pElementID
	 *		must be set as *HTML:pElementID as callback
 	 *		@param	{Int}		pID		id of the request in the queue
 	 *		@return	{Bool}		true
	 */
	pics.Ajax.setHTML = function(pID)
	{
		var lElement=pics.Ajax.requests[pID]["callback"].substr(6);
		if (lElement=='EXTRA') lElement=pics.Ajax.requests[pID]["extra"];	// if element-id is EXTRA, use the object stored in the Extra-Array
		pics.setHTML(lElement,pics.Ajax.requests[pID]["result"]);
		return true;
	}; // pics.Ajax.setHTML 
	

	/**
	 * pics.Ajax.setOPTION(pID)
	 *		internal setOPTION-CallBack-handler
	 *		add the result as option-elements for element with pElementID
	 *		must be set as *OPTION:pElementID as callback
 	 *		@param	{Int}		pID		id of the request in the queue
 	 *		@return	{Bool}		true
	 */
	pics.Ajax.setOPTION = function(pID)
	{
		lElement=pics.Ajax.requests[pID]["callback"].substr(8);
		// TODO: NOT IMPLEMENTED NOW !!!
		return true;
	}; // pics.Ajax.setOPTION
	

	/**
	 * pics.Ajax.loadContent()
	 *		load content via ajax 
	 *		@param	{String}	pUrl			url for the save-handler, if missing taken from the form.action
	 *		@param	{String}	pDest			id of destination-element for content
	 *		@param	{Mixed}		pForm			optional: id or element of the form with the data to POST
	 *		@return	
	 *	@return	
	 */
	pics.Ajax.loadContent = function(pUrl, pDest, pForm) 
	{
		if (pics.isUndefined(pUrl))			pUrl='';
		if (pics.isUndefined(pDest))		return false;

		// show loading animation in the content
		pics.setHTML(pDest,'<div class="p-loading32">loading ...</div>');
		
		// get params if a form is given
		var lParams='';
		if (!pics.isUndefined(pForm))
		{
			var oForm=pics.obj(pForm);
			if (!oForm) return false;
			lParams=pics.Form.convert2Params(oForm);
			// if url is empty, fetch from Form
			if (pUrl=='')		pUrl=oForm.action;
		} // if form

		pics.Ajax.request(pUrl, '*HTML:'+pDest, "POST", lParams);
		return true;
	}; // pics.Ajax.loadContent
	
	/**
	 * pics.Ajax.load()
	 *		load content via ajax in pics-json-return-format 
	 *		@param	{String}	pUrl			url for the save-handler, if missing taken from the form.action
	 *		@param	{String}	pDest			id of destination-element for content
	 *		@param	{Mixed}		pForm			optional: id or element of the form with the data to POST
	 *		@return	
	 *	@return	
	 */
	pics.Ajax.load = function(pUrl, pDest, pForm) 
	{
		if (pics.isUndefined(pUrl))			pUrl='';
		if (pics.isUndefined(pDest))		return false;

		// show loading animation in the content
		pics.setHTML(pDest,'<div class="p-loading32">loading ...</div>');
		
		// get params if a form is given
		var lParams='';
		if (!pics.isUndefined(pForm))
		{
			var oForm=pics.obj(pForm);
			if (!oForm) return false;
			lParams=pics.Form.convert2Params(oForm);
			// if url is empty, fetch from Form
			if (pUrl=='')		pUrl=oForm.action;
			// add pjr-param
			pUrl = pUrl + (pUrl.indexOf('?')==-1 ? '?' : '&' ) + 'pjr=1';
		} // if form

		pics.Ajax.request(pUrl, '*PJR:'+pDest, "POST", lParams, oForm);
		return true;
	}; // pics.Ajax.load	
	
