/**
 *  ****************************************************************************
 *  File : design/previmer/javascript/previmer_toolkit.js
 *  vers : 1.1
 *  build: 20070731
 *  Author : Virtualys
 *  ****************************************************************************
 **/

/**
 * Script de gestion de la page d'affichage des résultats Previmer.
 * (c) 2007 Ifremer - Virtualys / Tous droits réservés 
 */ 

/////
// Objets utilitaires
/////

/**
 * Convertit un tableau en noeud DOM, en y ajoutant la méthode item() suivante.
 */ 
Array.prototype.item = function(index) {
	return this[index];
}

/**
 * Boîte à outils.
 */ 
PrevimerToolkit = { }
/**
 * Gestion des instances globales et de l'héritage d'objets.
 */ 
PrevimerToolkit._NEXT_GI_ID = 0;
PrevimerToolkit._globalInstances = [];
PrevimerToolkit.getGlobalInstance = function(objectID) {
	return PrevimerToolkit._globalInstances[objectID];
}
PrevimerToolkit.registerGlobalInstance = function(object) {
	object._objectID =
		(object.className ? object.className : 'Object') + '-' +
		(PrevimerToolkit._NEXT_GI_ID++);
	PrevimerToolkit._globalInstances[object._objectID] = object;
	return object._objectID;
}
PrevimerToolkit.inherits = function(subClass, baseClass) {
	function Inheritance() { }
	Inheritance.prototype = baseClass.prototype;
	
	subClass.prototype = new Inheritance();
	subClass.prototype.constructor = subClass;
	subClass.superConstructor = baseClass;
	subClass.superClass = baseClass.prototype;
}
/**
 * Convertit une valeur géographique en représentation textuelle.
 * @param value la valeur numérique
 * @param longitude true si la valeur est une longitude, false sinon
 * @return le label  
 */ 
PrevimerToolkit.toDMS = function (value, longitude) {
	var absvalue = Math.abs(value);
	var deg = Math.floor(absvalue);
	var min = Math.floor((absvalue*60)%60);
	var sec = Math.floor((absvalue*3600)%60);

	var result = deg + '&deg;';
	if (min > 0)
	{
		result += min + '&#x27;';
	}
	if (sec > 0)
	{
		result += sec + '&#x22;';
	}
	if (value < 0)
	{
		if (longitude)
		{
			if (PrevimerToolkit.locale == 'fr')
			{
				return result + 'O';
			}
			return result + 'W';
		}
		return result + 'S';
	}
	if (longitude)
	{
		return result + 'E';
	}
	return result + 'N';
}
/**
 * Obtient un service Ajax en fonction d'un nom de service et des paramètres.
 */ 
PrevimerToolkit.getService = function(serviceName, parameters) {
	var service = serviceName;
	for (var key in parameters) {
		service += '/';
		if (parameters[key] instanceof Array) {
			for (var i = 0; i < parameters[key].length; ++i) {
				if (i != 0) {
					service += '/';
				}
				service += key + '/' + parameters[key][i];
			}
		}
		else
			service += key + '/' + parameters[key];
	}
	return service;
}
/**
 * Lit un cookie.
 */ 
PrevimerToolkit.getCookie = function(nom, defaultValue)
{
	var pos = document.cookie.indexOf(nom + "=");
	if (pos == -1) {
		return defaultValue;
	}
	var endPos = document.cookie.indexOf(";", pos);
	if (endPos == -1) {
		return unescape(document.cookie.substring(pos + nom.length + 1));
	}
	return unescape(document.cookie.substring(pos + nom.length + 1, endPos));
}
/**
 * Met à jour un cookie.
 */ 
PrevimerToolkit.setCookie = function(name, value) {
	var argv = PrevimerToolkit.setCookie.arguments;
	var argc = PrevimerToolkit.setCookie.arguments.length;
	var expires = (argc > 2) ? argv[2] : null;
	var path = (argc > 3) ? argv[3] : null;
	var domain = (argc > 4) ? argv[4] : null;
	var secure = (argc > 5) ? argv[5] : false;
	document.cookie = name + "=" + escape(value) +
		((expires == null) ? "" : ("; expires=" + expires.toGMTString()))+
		((path == null) ? "" : ("; path=" + path))+
		((domain == null) ? "" : ("; domain=" + domain))+
		((secure == true) ? "; secure" : "");
}
/**
 * Obtient une URL complète d'accès à un résultat.
 */ 
PrevimerToolkit.getResultRequest = function(params, config) {
	var url = config.ajaxServer + PrevimerToolkit.getService('getResult', params);
	if (config.ajaxProxy) {
		url = config.ajaxProxy + escape(url);
	}
	return url;
}
/**
 * Appelle une méthode passée en argument. Cette fonction gère les méthodes
 * statiques ou dynamiques. 
 */ 
PrevimerToolkit.callMethod = function(method, param) {
	if (typeof(method) == 'string') {
		// fonction à évaluer
		var index = method.lastIndexOf('.');
		if (index != -1) {
			var instance = eval(method.substring(0, index));
			instance[method.substring(index + 1)].call(instance, param);
		}
		else {
			(eval(method))(param);
		}
	}
	else {
		// fonction
		method(param);
	}
}
/**
 * Ajoute une méthode pour obtenir les fils directs uniquement d'un noeud DOM.
 * @param node le noeud parent 
 * @param name le nom des balises enfants directs à rechercher 
 */ 
PrevimerToolkit.getChildrenByTagName = function(node, name) {
	 return false;
	var nodes = new Array();
	var child = node.firstChild;
	while (child) {
		if (child.nodeType == 1 // element
				&& child.nodeName == name) {
			nodes.push(child);
		}
		child = child.nextSibling;
	}
	return nodes;
}
////
////

/**
 * ============================================================================= 
 * VAjaxEngine
 * Moteur VAjax.
 * ============================================================================= 
 *
 * @param server l'adresse du serveur producteur du flux XML
 * @param responseHandler fonction à appeler lors de la réception d'une réponse
 * valide  
 */
VAjaxEngine = function(server, responseHandler, errorHandler) {
	// Contexte Ajax
	this._context = {
			'server' : server.ajaxServer,
			'proxy'  : server.ajaxProxy,
			'lastRequest' : null,
			'connector' : null,
			'lastDocument' : null
	};
	
	// Méthode
	this._method='GET';
	// Synchrone ou asynchrone
	this._async = true;
	// Données à transmettre au serveur (utilisées généralement en POST)
	this._dataToSend=null;
	// Event handler recevant les notifications de l'avancée
	// du chargement
	this._handleEvent = null;
	// Event handler déclenché lorsque le chargement est réalisé
	if (responseHandler) {
		this._handleResponse = responseHandler;
	}
	else {
		this._handleResponse = null;
	}
	// Event handler déclenché lorsque le chargement est tombé en erreur
	if (errorHandler) {
		this._handleError = errorHandler;
	}
	else {
		this._handleError = function(context) {
			if (context.connector) {
				alert(
					'[' + context.server + context.lastRequest + '] Request error : ' +
					context.connector.status + '(' + context.connector.statusText + ')');
			}
			else {
				alert('Bad connector - Ajax not supported');
			}
		}
	}
}

VAjaxEngine.prototype = {
/**
 * -----------------------------------------------------------------------------
 * Enregistre un gestionnaire de réponse.
 * @param response le gestionnaire à enregistrer
 */      
	'registerResponseHandler' : function(response) {
		this._handleResponse = response;
	},
/**
 * -----------------------------------------------------------------------------
 * Enregistre les gestionnaires de requêtes.
 * @param response le gestionnaire de réponse à enregistrer
 * @param err le gestionnaire d'erreur à enregistrer
 * @param event le gestionnaire d'événements à enregistrer
 */
	'registerHandlers' : function(event, response, err) {
		this._handleEvent = event;
		this._handleResponse = response;
		this._handleError = err;
	},
/**
 * -----------------------------------------------------------------------------
 * Effectue une requête GET.
 * @param service le service à appeler
 */
	'doGet' : function(service) {
		this._context.lastRequest = service;
		this._dataToSend = null;
		this._method = 'GET';
		this._sendRequest();
	},
/**
 * -----------------------------------------------------------------------------
 * Effectue une requête HEAD.
 * @param service le service à appeler
 */
	'doHead' : function(service) {
		this._context.lastRequest = service;
		this._dataToSend = null;
		this._method = 'HEAD';
		this._sendRequest();
	},
/**
 * -----------------------------------------------------------------------------
 * Effectue une requête POST.
 * @param service le service à appeler
 * @param postData les données à transmettre
 */
	'doPost' : function(service, postData) {
		this._context.lastRequest = service;
		this._dataToSend = postData;
		this._method = 'POST';
		this._sendRequest();
	},
/**
 * -----------------------------------------------------------------------------
 * Interrompt une requête en cours.
 */
	'abort' : function() {
		if (this._context.connector) {
			this._context.connector.onreadystatechange = function() { };
			this._context.connector.abort();
			this._context.connector = null;
		}
	},
/**
 * -----------------------------------------------------------------------------
 * Obtient le contexte d'exécution Ajax, contenant le connecteur ainsi que les
 * principaux paramètres associés à la requête.
 * @return le contexte
 */ 
	'getContext' : function() {
		return this._context;
	},
/**
 * -----------------------------------------------------------------------------
 * Obtient un connecteur Ajax vers le serveur.
 * @return le connecteur ou null
 */
	'_getConnector' : function() {
		if (this._context.connector == null) {
			if (window.XMLHttpRequest) {
				try {
					this._context.connector = new XMLHttpRequest();
				}
				catch(e) {
					return null;
				}
			}
			else if (window.ActiveXObject) {
				try {
					this._context.connector = new ActiveXObject("Msxml2.XMLHTTP");
				}
				catch(e) {
					try {
						this._context.connector = new ActiveXObject("Microsoft.XMLHTTP");
					}
					catch(e) {
						return null;
					}
				}
			}
			else {
				return null;
			}

			var self = this;
			this._context.connector.onreadystatechange = function() {
				if (self._handleEvent != null) {
					self._handleEvent(self._context);
				}

				if (self._context.connector.readyState == 4) {
					if (self._context.connector.status >= 200 && self._context.connector.status <= 299) {
						if (self._context.connector.responseXML) {
							self._context.lastDocument = self._context.connector.responseXML.documentElement;
						}
						else {
							self._context.lastDocument = null;
						}
						if (self._handleResponse != null) {
							PrevimerToolkit.callMethod(self._handleResponse, self._context);
						}
					}
					else {
						self._context.lastDocument = null;
						if (self._handleError != null) {
							PrevimerToolkit.callMethod(self._handleError, self._context);
						}
					}
				}
			};
		}
		return this._context.connector;
	},
/**
 * -----------------------------------------------------------------------------
 * Envoie une requête générique au serveur.
 * @param service la requête à appeler (un chemin en rapport avec l'url du serveur)
 */
	'_sendRequest' : function() {
		/*
		var connector = this._getConnector();
		if (connector == null) {
			if (this._handleError == null) {
				alert('Can\'t connect to server.');
			}
			else {
				this._handleError(this._context);
			}
			return;
		}
		try {
			var url = this._context.server + this._context.lastRequest;
			if (this._context.proxy) {
				url = this._context.proxy + escape(url);
			}
			connector.open(this._method, url, this._async);
			connector.send(this._dataToSend);
		}
		catch (e) {
			this._handleError(this._context);
		}
		*/
		var url = this._context.server + this._context.lastRequest;
		if (this._context.proxy) {
			url = this._context.proxy + escape(url);
		}
		var that = this;
		try
		{
			var connector = this._context.connector = $.ajax({
				async		: that._async,
				type		: that._method,
				xhr			: function(){
					return that._getConnector();
				},
				url			: url
			});
		}catch(e)
		{
			this._handleError(this._context);
		}
	}
}
