/**
	pics.ajax.js
	Desc:	Ajax-Framework für parallele Requests und Debugging

	basiert auf pics.base, arbeitet aber autark
	
	Author: Christian Grösswang
	
	20061227,gc - v1.00		Prototype + Test
	20080918,gc - v1.01		Bug bei leerem Post behoben
**/




/*
	Funktionsübersicht 
	
	Ajax-Framework:
		pics.Ajax.init 			Framework initialisieren
		pics.Ajax.request		Request absetzen
		pics.Ajax.createXMLHttpRequestObject	XMLHttp-Objekt erzeugen, wird nur intern verwendet
		pics.Ajax.callBack		allgemeiner Callback-Handler, wird nur intern verwendet
		pics.Ajax.setHTML		allgemeiner HTML-Callback-Handler, wenn beim Request als Callback "*HTML:ElementID"
		pics.Ajax.setOPTION		allgemeiner Option-Tag-Callback-Handler, wenn beim Request als Callback "*OPTION:ElementID"  (NOT IMPLEMENTED NOW!!!)
		pics.Ajax.getResult		Ergebnis zu einem Request holen

*/


// Constructor, falls das PICS-Framework nicht geladen ist
	if (typeof pics == 'undefined') pics = {};

/* 
 *	====================================================================================
 *	===== FRAMEWORK: pics.Ajax 														====
 *	====================================================================================
 */

	/**
	 *	Ajax-Protokoll via Array
	 *	Um mehr flexibilität zu erhalten und vor allem das ganze besser debuggen zu können
	 *	packe ich das ganze AJAX-Zeugs ein eine Klasse und ein Array, die nicht nur mehrere
	 *	Anfragen verwaltet, sondern auch die Ergebnisse für Debugging zwischenspeichert.
	 *	
	 *	Welche Werte speichere ich pro Request
	 *	- URL
	 *	- Methode GET/POST
	 *	- Callback-Handler
	 *	- Post-Parameter
	 *	- State
	 *	- Result
	 *	- Timestamp
	 *	
	 *	Zusätzlich gibt es dann noch ein paar Debug-Funktionen, z.B.
	 *	ajaxShowRequestList(pDestObject, pSize=10);
	 *	ajaxShowRequest(pDestObject, pID);
	 *	
	 */

	// Constructor
	if (typeof pics.Ajax == 'undefined') pics.Ajax = {};

	/**
	 * pics.Ajax.init()
	 *		Ajax-Basisobjekt initialisieren und Variablen vorbelegen
	 */
	pics.Ajax.init = function() 
	{
		// Array für die Requests definieren
		pics.Ajax.Requests=new Array();
		// Debug-Variable reseten
		pics.Ajax.debug=false;
		pics.Ajax.debuglog='';
	} // pics.Ajax.init

	/**
	 * pics.Ajax.request()
	 *		neuen Request absetzen
 	 *	@param	string	pUrl		URL die aufgerufen wird
 	 *	@param	string	pCallback	Callback-Handler 
	 *								( interne Callback-Handler: *HTML:Element   *OPTION:Element	)
 	 *	@param	string	pMethod		GET/POST ( default = GET )
 	 *	@param	string	pPostParams	Parameter für POST
 	 *	@return	int		ID im Array für den Aufruf
	 */
	pics.Ajax.request = function(pUrl, pCallback, pMethod, pPostParams)
	{
		// Parameter prüfen und zur not überschreiben
		if (typeof pUrl		=='undefined') return false;
		if (typeof pCallback	=='undefined') return false;
		if (typeof pMethod		=='undefined') pMethod='GET';
		if (typeof pPostParams	=='undefined') pPostParams='';

		// nächste Position im Array ermitteln und anlegen
		lID=pics.Ajax.Requests.length;
		pics.Ajax.Requests[lID]=new Array();
		// Parameter zuweisen
		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]["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';
		
		// 20070823,gc - um Caching zu verhindern erweitere ich hier die URL um einen Timestamp
		pUrl=pUrl+'&picsts='+pics.Ajax.Requests[lID]["timestamp"].getTime();
		
		// jetzt erzeugen wir ein Objekt
		pics.Ajax.Requests[lID]["object"]=pics.Ajax.createXMLHttpRequestObject();
		
		// und starten den Request		
		pics.Ajax.Requests[lID]["object"].open(pMethod,pUrl,true);	// asynchrone Verbindung starten
		
		// setzen den Callback-Handler
		pics.Ajax.Requests[lID]["object"].onreadystatechange=pics.Ajax.callBack(lID);
		
		lSendParam=null;
		if (pMethod=="POST") // Request als POST senden 
		{
			// 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.Requests[lID]["object"].send(null);
		return true;
	} // pics.Ajax.request
	
	
	/**
	 * pics.Ajax.request_sync()
	 *		synchronen Request absetzen 
 	 *	@param	string	pUrl		URL die aufgerufen wird
 	 *	@param	string	pMethod		GET/POST ( default = GET )
 	 *	@param	string	pPostParams	Parameter für POST
 	 *	@return	string	rückgabe des Requests
	 */
	pics.Ajax.request_sync = function(pUrl, pMethod, pPostParams)
	{
		// Parameter prüfen und zur not überschreiben
		if (typeof pUrl		=='undefined') return false;
		if (typeof pMethod		=='undefined') pMethod='GET';
		if (typeof pPostParams	=='undefined') pPostParams='';

		// nächste Position im Array ermitteln und anlegen
		lID=pics.Ajax.Requests.length;
		pics.Ajax.Requests[lID]=new Array();
		// Parameter zuweisen
		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';
		
		// jetzt erzeugen wir ein Objekt
		pics.Ajax.Requests[lID]["object"]=pics.Ajax.createXMLHttpRequestObject();
		
		// und starten den Request		
		pics.Ajax.Requests[lID]["object"].open(pMethod,pUrl,false);	// synchrone Verbindung starten
		
		if (pMethod=="POST") // Request als POST senden 
		{
			// Header definieren
			pics.Ajax.Requests[lID]["object"].setRequestHeader("Content-Type","application/x-www-form-urlencoded");
			if (pPostParams!='') pics.Ajax.Requests[lID]["object"].send(pPostParams);
		}
		else
		{
			pics.Ajax.Requests[lID]["object"].send(null);
		}

		// Ergebnis auswerten
		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;
		}
		return pics.Ajax.Requests[lID]["result"];
	} // pics.Ajax.request_sync
	
	
	/**
	 * pics.Ajax.getResult()
	 *		Ergbnis des entsprechenden Querys absetzen
 	 *	@param	int		pID 		ID in der Queue
 	 *	@return	string	result des aufrufs
	 */
	pics.Ajax.getResult = function(pID)
	{
		if (!pics.Ajax.Requests[pID]["result"]) return "";
		return pics.Ajax.Requests[pID]["result"];
	} // pics.Ajax.getResult
	
	
	/**
	 * pics.Ajax.createXMLHttpRequestObject()
	 *		neues XML/HTTP-Objekt erzeugen
 	 *	@return	object/false		XML/HTTP-Objekt
	 */
	pics.Ajax.createXMLHttpRequestObject = function()
	{
		var oRequest=false;
	    // Unterstützt der Browser das XMLHttpRequest-Objekt von Apple
	    if (window.XMLHttpRequest) 
		{
	    	try 	{ oRequest = new XMLHttpRequest(); } 
			catch(error) { oRequest = false; }
	    } // Unterstützt der Browser die 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!");
		
		// Rückgabe
		return oRequest;		
	}


	/**
	 * pics.Ajax.callBack(pId)
	 *		CallBack-Handler für Ajax
	 *		WICHTIG ist der TRICK mit return function, da sonst die neuen Handler die alten überschrieben
	 *		Gefunden bei twobirds.js
 	 *	@param	int			pID		ID des Aufrufs
 	 *	@return	boolean		true
	 */
	pics.Ajax.callBack = function(pID)
	{
	  return function () 
	  {
		if (typeof pics.Ajax.Requests[pID]["object"] == 'undefined')
		{
			alert("Request "+pID+" nicht vorhanden!");
			return false;
		}
		pics.Ajax.Requests[pID]["state"]=pics.Ajax.Requests[pID]["object"].readyState;

		// Debug ?
		if (pics.Ajax.debug) pics.Ajax.debuglog+='pics.Ajax.callBack('+pID+') state: '+pics.Ajax.Requests[pID]["state"]+'\n';

//		alert("Callback for Request "+pID+' State:'+pics.Ajax.Requests[pID]["state"]);
		// 0: Initialisiert, 1: Wird geladen, 2: Fertig geladen, 3: Interaktiv, 4: Fertig
		if (pics.Ajax.Requests[pID]["state"] == 4)
		{
			pics.Ajax.Requests[pID]["result"]=pics.Ajax.Requests[pID]["object"].status;

			// Debug ?
			if (pics.Ajax.debug) pics.Ajax.debuglog+='pics.Ajax.callBack('+pID+') status: '+pics.Ajax.Requests[pID]["result"]+'\n';

//			alert("Callback for Request "+pID+' Result:'+pics.Ajax.Requests[pID]["result"]);
			if (pics.Ajax.Requests[pID]["result"] == 200) 
			{
				// laden war erfolgreich, also merken wir uns den Inhalt
				pics.Ajax.Requests[pID]["result"] = pics.Ajax.Requests[pID]["object"].responseText;
				// und rufen wir den eigentlichen Callback-Handler auf
//				alert('FINISH: \n'+'Callback:'+pics.Ajax.Requests[pID]["callback"]+'\n'+pics.Ajax.Requests[pID]["result"]);
				switch(pics.Ajax.Requests[pID]["callback"].substr(0,5))
				{
					case "*SILE":		// SILENT = Callback ignorieren
						break;
					case "*HTML":		// Interner HTML-Callback-Handler setHTML
						pics.Ajax.setHTML(pID);
						break;
					case "*OPTI":		// Interner OPTION-Tag-Callback-Handler setOPTION
						pics.Ajax.setOPTION(pID);
						break;
					case "*ALER":		// Interner Callback-Handler alert
						alert(pics.Ajax.Requests[pID]["result"]);
						break;
					case "*MSGB":		// Interner Callback-Handler msgbox
						lTime=pics.Ajax.Requests[pID]["callback"].substr(8);
						if (lTime=='') lTime=0;
						pics.Windows.msgBox(pics.Ajax.Requests[pID]["result"], true, true, lTime);
						break;
					default:			// individuelle Funktion
//						eval(pics.Ajax.Requests[pID]["callback"]+"('"+encodeURI(pics.Ajax.Requests[pID]["result"])+"')");
						eval(pics.Ajax.Requests[pID]["callback"]+"(pics.Ajax.getResult("+pID+"))");
						break;
				}
			}
			else 
			{
				alert("Es ist ein interner Fehler bei Request ("+pID+") aufgetreten:\n" + pics.Ajax.Requests[pID]["object"].statusText);
			}
			// auf jeden Fall zerstören wir das Objekt jetzt wieder
			pics.Ajax.Requests[pID]["object"]=null
			
		}	
	  }
	}
	
	/**
	 * pics.Ajax.setHTML(pID)
	 *		setHTML-CallBack-Handler für Ajax
	 *		muss als *HTML:pElementID beim Request angegeben werden
	 *		setzt das innerHTML beim Element pElementID
 	 *	@param	int			pID		ID des Aufrufs
 	 *	@return	boolean		true
	 */
	pics.Ajax.setHTML = function(pID)
	{
		lElement=pics.Ajax.Requests[pID]["callback"].substr(6);
		oElement=document.getElementById(lElement);
		oElement.innerHTML=pics.Ajax.Requests[pID]["result"];
		return true;
	}
	

	/**
	 * pics.Ajax.setOPTION(pID)
	 *		setOPTION-CallBack-Handler für Ajax
	 *		muss als *OPTION:pElementID beim Request angegeben werden
	 *		setzt die OPTION-Elemente beim Element pElementID
 	 *	@param	int			pID		ID des Aufrufs
 	 *	@return	boolean		true
	 */
	pics.Ajax.setOPTION = function(pID)
	{
		lElement=pics.Ajax.Requests[pID]["callback"].substr(8);
		// NOT IMPLEMENTED NOW !!!
//		oElement=document.getElementById(lElement);
//		oElement.innerHTML=pics.Ajax.Requests[pID]["result"];
		return true;
	}
	


/* 
 *	====================================================================================
 *	===== GLOBALE INITALISIERUNG													====
 *	====================================================================================
 */

	 
// Ajax-Framework-Initialisieren
	pics.Ajax.init();

	 
