function swapContent(element)
{
	element.innerHTML = element.innerHTML.replace(/\b([A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,4})\b/gi, "<a href=\"mailto:$1\">$1</a>");
	element.innerHTML = element.innerHTML.replace(/\b[^'\"](https?|ftp|file):\/\/([-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, "<a href=\"$1:\/\/$2\">$2</a>");
}


function parseHtml()
{
	var annonces = document.getElementById('listingAnnonce');
	if (annonces)
	{
		swapContent(annonces);
	}
};

var Widget = {};
var Controller = {};
Controller.prototype = {
	addEventListener: function(element, name, observer, useCapture) {
		if (typeof (observer) == "function")
			observer = observer.bindAsEventListener(this)

		Event.observe(element, name, observer, useCapture);
		return false;
	}
}

document.ctrl = {};

var OOAF = document.OOAF = {
	uniqIdCt:0,
	version:'0.1b',
	scriptPath:'/scripts/',
	cssPath:'/css/',
	imgPath:'/images/',
	loaded:{},	/* Library already loaded have true value */
	nbCurReq:0,
	xml:{},
	xsl:{},
	container:{},
	tags:[],
	debug:0,
	debugWin:null,
	debugTxt: "",
	listView:{},
	isLogDisplayed:0,
	nbNotify:0,
	/*
	Fonctions d'inclusions
	*/
	require: function(scriptName) {
		if (typeof scriptName == "string") {
			if (!this.loaded[scriptName]) {
				document.write('<script type="text/javascript" src="'+ this.scriptPath + scriptName+'"></script>');
				this.loaded[scriptName] = true;
			}
		}
	},
	includeCss: function(cssName, absoluteURI) {
		if (absoluteURI) {
			document.write('<link type="text/css" rel="stylesheet" href="'+ this.cssName +'" media="screen"/>');
		} else {
			document.write('<link type="text/css" rel="stylesheet" href="'+ this.cssPath + cssName+'" media="screen"/>');
		}
	},
	/*
	Fonctions de chargements des differentes librairies
	*/
	loadWidget: function() {
//		this.require('Widget/Calendar.js');
//				this.require('Widget/Window.js');
		//		this.require('Widget/ColorChooser.js');
		//		this.require('Widget/Frequency.js');
	},
	loadController: function() {
		this.require('Controller/Form.js');
		this.require('Controller/Search.js');
		this.require('Controller/Datagrid.js');
		this.require('Controller/Modal.js');
		this.require('Controller/Popmenu.js');
//		this.require('Controller/Tabs.js');
//		this.require('Controller/Autocomplete.js');
//		this.require('Controller/LiveClipboard.js');
	},
	loadMinimum: function() {
		this.require('cssQuery-p.js');
		this.require('prototype.js');
		this.require('prototypeExtended.js');
		this.require('scriptaculous.js');
		this.require('breakpoint.js');
//		this.require('DHTMLAPI.js');
		this.require('base64.js');
		this.require('template.js');
	},
	loadYahooUI: function() {
		this.require('yahoo/dom/build/YAHOO.js');
		this.require('yahoo/dom/build/dom.js');
		this.require('yahoo/event/build/event.js');
		this.require('yahoo/calendar/build/calendar.js');
	},
	loadBase: function() {
		this.includeCss('UI.css');
		this.loadMinimum();
		this.loadMochiKit();
	},
	loadMochiKit: function() {
		this.require('MochiKit.js');
	},
	/*
	Fonction de chargement de base
	*/
	load: function(libs) {
		this.loadBase();

		for (var i in libs) {
			for (var j in libs[i]) {
				var libPath = i + "/" + libs[i][j] + ".js";
				this.require(libPath);
			}
		}
	},
	/*
	Fonction d'initialisation du framework
	*/
	init: function(options) {
		if (document.location.href.indexOf("debug=1") > 0) {
			OOAF.debug = true;
			createLoggingPane(true);
			OOAF.isLogDisplayed = 1;
		}
		Object.extend(this, options);
		//		if (this.loaded['Controller/Form.js'] == true) {
		//			OOAF.cal = new Widget.Calendar('uniqCalendar', {lng:"fr",hide:true});
		//			OOAF.cal.hide();
		//		}

		// Gestion des liens
		document.onclick = show.bindAsEventListener(this);

		new Insertion.Top(document.body, '<div id="notifyContainer"></div>');
		new Insertion.Top(document.body, '<div id="cursorContainer"></div>');
		document.onmousemove = OOAF.moveCursorContainer.bindAsEventListener(this);
		document.onkeypress = OOAF.handleShortcut.bindAsEventListener(this);
		// Gestion du menu contextuel
		//		DHTML.insertHTML('<div id="contextMenu"></div>');
		//		document.oncontextmenu=OOAF.affMenu;

		Element.hide('notifyContainer');
		Element.setStyle("cursorContainer", {
			zIndex:100000
		});

		if (options && options.onComplete)	options.onComplete();
	},

	handleShortcut: function(e) {
		var key = Browser.isIE() ? e.keyCode : e.which;
//		breakpoint(function(expr) { return eval(expr) });
		if (key == "D".charCodeAt(0)) {
			if (!OOAF.debug) {
				createLoggingPane(true);
				OOAF.debug = 1;
			}
			if (!OOAF.isLogDisplayed) {
				OOAF.isLogDisplayed = 1;
				Element.show('_MochiKit_LoggingPane');
			} else {
				OOAF.isLogDisplayed = 0;
				Element.hide('_MochiKit_LoggingPane');
			}
		}
	},

	affMenu: function(e) {
		if (document.all) {
			var posX = document.body.scrollLeft+event.clientX;
			var posY = document.body.scrollTop+event.clientY;
		} else {
			var posX = e.pageX;
			var posY = e.pageY;
		}
		$('contextMenu').style.display = "block";
		$('contextMenu').style.position = "absolute";
		$('contextMenu').style.left = posX + "px";
		$('contextMenu').style.top = posY + "px";
	},
	/*
	Fonction de hover
	*/
	displayTitle: function(tgt) {
//		tgt = Event.element(evt);
		var html = tgt.getAttribute('ooaf_title');
		OOAF.enableHover(html);
	},
	displayHover: function(tgt) {
//		tgt = Event.element(evt);
		if (tgt.getAttribute('ooaf_title'))
		return;
		var url = tgt.getAttribute('ooaf_hover');
		OOAF.hasHover = true;
		view(null, url, {onComplete:function (req) {
			var html = req.responseText;
			tgt.setAttribute('ooaf_title', html);
			if (OOAF.hasHover == true)
			OOAF.enableHover(html);
		}});
	},
	activeHover: function() {
//		document.onmouveover = OOAF.displayTitle.bindAsEventListener(this);

//		DHTML.addEventListener("mouseover", OOAF.displayTitle, document, "ooaf_title:/.+/");
//		DHTML.addEventListener("mouseover", OOAF.displayHover, document, "ooaf_hover:/.+/");

//		DHTML.addEventListener("mouseout", OOAF.disableHover, document, "ooaf_title:/.+/");
//		DHTML.addEventListener("mouseout", OOAF.disableHover, document, "ooaf_hover:/.+/");
	},
	enableHover: function(content) {
		if ($('cursorContainer')) {
			Element.show($('cursorContainer'));
			$('cursorContainer').innerHTML = content;
		}
	},
	disableHover: function() {
		OOAF.hasHover = false;
		OOAF.clearHover();
	},
	clearHover: function() {
		if ($('cursorContainer')) {
			Element.hide($('cursorContainer'));
			$('cursorContainer').innerHTML = "";
		}
	},
	moveCursorContainer: function(evt){
		var availDim = Browser.getAvailableDimensions();

		var curX = Event.pointerX(evt);
		var curY = Event.pointerY(evt);
		var widthContainer = $('cursorContainer').offsetWidth;
		var availWidth = availDim.width - widthContainer - curX;

		if(widthContainer && availWidth < widthContainer) {
			$('cursorContainer').style.left = (curX - widthContainer) + "px";
		} else if (widthContainer && availWidth >= widthContainer) {
			$('cursorContainer').style.left = curX + "px";
		}
		$('cursorContainer').style.top = (curY + 20) + "px";

		//		$('debug').innerHTML = [curX, curY] + " " + availDim + " " + window.innerWidth;

	},

	startRequest: function() {
		OOAF.nbCurReq++;
		OOAF.enableHover("<img src='" + this.imgPath + "searching.gif'/>Chargement... " + OOAF.nbCurReq);
	},

	endRequest: function() {
		OOAF.nbCurReq--;
		OOAF.enableHover("<img src='" + this.imgPath + "searching.gif'/>Chargement... " + OOAF.nbCurReq);
		if (OOAF.nbCurReq == 0) {
			OOAF.clearHover();
		}
	},

	registerListView: function(listName, listView) {
		this.listView[listName] = listView;
	},

	/**
	* @param mixed $options liste:
	* - params parametres pass?s a chaque updateView
	* - filters filtres les vues a raffraichir par leur parametres (contenu dans le lastView)
	* - except tableau de vues a ne pas raffraichir
	*
	*/
	updateViewList: function(eventName, options) {
		eventName = "on" + eventName.toLowerCase();
		var debugMsg = "refreshing all: <br/>";

		if (this.listView[eventName]) {
			if (options && options.except) {
				var except = [];
				if (typeof(options.except) == "string") {
					options.except = new Array(options.except);
				}
				for (var j = 0; j < options.except.length; j++) {
					except.push(options.except[j].split("/"));
				}
			}
			for (var i=0; i < this.listView[eventName].length; i++) {
				var skipview = false;
				var testview = this.listView[eventName][i];

				if (options && options.except) {
					var explodedview = testview.split("/");

					for (var j = 0; j < except.length; j++) {
						if (explodedview[1] == except[j][1] && explodedview[2] == except[j][2]) {
							debugMsg += "passed view "+testview+"<br />";
							skipview = true;
						}
					}
					if (skipview == true) {
						continue;
					}
				}
				var regs = testview.match(/%([^%]+)%/g);
				if (regs) {
					for (var j=0; j < regs.length; j++) {
						var prop = regs[j].substr(1, regs[j].length-2);
						var replaceValue = (options && options.filters[prop]) ? options.filters[prop] : '';
						testview = testview.replace(regs[j], replaceValue);
					}
				}
				var params = (options && options.params) ? options.params : null;
				OOAF.updateViews(testview, params);
				debugMsg += "\t - " + testview + "<br />";
			}
		} else {
			OOAF.w({title:"OOAF.updateViewList",content:"event '" + eventName + "' is not defined"});
		}
		debugMsg += " <br>with options: " + options;
		OOAF.d({title:"OOAF.updateViewList: "+eventName,content:debugMsg,duration:8000});
	},

	updateViews: function(url, params) {
		var listContainers = document.getElementsBySelector('[lastView]');
		var regexpurl = new RegExp(url);

		var deb = "";
		for (var i=0; i<listContainers.length; i++) {
			var lastView = listContainers[i].getAttribute('lastView');
			var matchUrl = lastView.match(regexpurl);
			var nextChars = lastView.substring(url.length);

			if (matchUrl && (nextChars[0] == "/" || nextChars[0] == undefined)) {
				var onChange = listContainers[i].getAttribute('onChangeData');
				if (onChange) {
					// ATTENTION EVAL DANS CONTEXT!
					eval(onChange);
				} else {
					deb += "refreshing: " + lastView + "<br />";
					OOAF.refreshContainer(listContainers[i], params);
				}
			}
		}

		if (deb == "") {
			deb = "0 view updated for " + url;
		}

		OOAF.d({title:"OOAF.updateViews",content:deb,duration:3000});
	},

	errorHandler: function(error, file, line) {
		logError("JS:" + file + ": at line " + line + "<br/>" + error);
	},

	notify: function(message, idTemplate) {
		this.nbNotify++;
		Element.show('notifyContainer');
		stringDate = toISOTimestamp(new Date());

		var id = OOAF.getUniqId();

		if (typeof(idTemplate) == 'undefined') {
			var msgContent = "<div id='"+id+"'>(" + stringDate + ") " + message + "</div>";
		} else {
			var msgContent = Template.process(idTemplate, {
				time:stringDate,
				message:message
			});
		}

		$('notifyContainer').innerHTML += msgContent;
		window.setTimeout(function() {
			Effect.Fade(id);
			this.nbNotify--;
			if (this.nbNotify == 0) {
				window.setTimeout(function() {
					$('notifyContainer').innerHTML = '';
					Element.hide('notifyContainer');
				}, 1000);
			}
		}.bind(this), this.nbNotify * 1000);
	},

	msg : function(title, content, className) {
		if (OOAF.debug == true) {
			if (className == "debug") {
				logDebug(title + ": " + content);
			} else if (className == "warning") {
				logWarning(title + ": " + content);
			}
		}
	},

	d : function(content, title) {
		title = title ? 'DEBUG: ' + title : 'DEBUG';
		OOAF.msg(title, content, 'debug');
	},

	w : function(content, title) {
		title = title ? 'WARNING: ' + title : 'WARNING';
		OOAF.msg(title, content, 'warning');
	},

	getUniqId: function(prefix) {
		var ret ='';
		if (prefix) {
			ret = prefix+ret;
		}
		ret += "IDTMP" + this.uniqIdCt;
		this.uniqIdCt++;
		return ret;
	},
	/**
	* Refresh a Container which was loaded with view()
	* @param {Node} domNode to refresh
	* @param {Array|Object} new Parameters to pass
	*
	* @see #view
	*/
	refreshContainer: function(container, newParams, options) {
		container = $(container);

		try {
			if (container.ooafurl) {
				var url = container.ooafurl;
			} else {
				var lastView = container.getAttribute('lastview');
				var url = new OOAFUrl(lastView);
			}
			//breakpoint(function(expr) { return eval(expr); }, "\nOOAF.refreshContainer('"+ container.id +"','"+newParams+"', '"+options+"')", url);

			if (newParams) {
				if (url instanceof OOAFUrl) {
					if (typeof (newParams) == "object") {
						// Si on passe un objet, on merge avec le premier parametre de l'url
						url.mergeParam(0, newParams);
					} else if (typeof (newParams) == "array") {
						// Si on passe un tableau, on merge les parametres un a un
						$A(newParams).each(function (param, idx) {
							url.mergeParam(idx, param);
						});
					} else {
						url.mergeParam(0, newParams);
					}
				} else if (url instanceof Url) {
					$H(newParams).each(function(param) {
						url.setGet(param.key, param.value);
					});
				}
			}
			if (options && options.get) {
				$H(options.get).each(function(param) {
					url.setGet(param.key, param.value);
				});
			}

			view(container, url.toString(), options);
		} catch (e) {
			logWarning(e + ": #" + container.id + " ne contient pas de vue");
		}

	},
	getFormValues: function(container) {
		var elements = Form.getElements(container);
		var values = [];

		for (var i = 0; i < elements.length; i++) {
			if (elements[i].type == "text") {
				var val = (elements[i].value != elements[i].title) ? Form.Element.serialize(elements[i]) : "";
				values.push(val);
			} else {
				values.push(Form.Element.serialize(elements[i]));
			}
		}

		return values.join('&');

		container = $(container);
		var formStr = '';
		$A(container.getElementsByTagName('input')).each(function(element) {
			switch (element.type) {
				case 'text':
				case 'password':
				case 'hidden':
				formStr += '&' + element.name + '=' + escape(element.value);
				break;
				case 'radio':
				case 'checkbox':
				if (element.checked == true)
				formStr += '&' + element.name + '=' + escape(element.value);
				break;
			}
		});
		$A(container.getElementsByTagName('select')).each(function(element) {
			var idx = 0;
			$A(element.options).each(function (option) {
				var name = element.name.replace("[]", "");

				if (option.selected) {
					if (element.getAttribute("multiple")) {
						formStr += '&' + name + '['+idx+']=' + escape(option.value);
						idx++;
					} else {
						formStr += '&' + name + '=' + escape(option.value);
					}
				}
			});
		});

		$A(container.getElementsByTagName('textarea')).each(function (element) {
			formStr += '&' + element.name + '=' + escape(element.value);
		});

		return formStr;
	},

	// a une certaine epoque, prototype faisait plante Firefox sur un .each
	evalScripts: function(responseText) {
		var scripts = responseText.extractScripts();
		for(i=0; i < scripts.length; i++) {
			eval(scripts[i]);
		}
	},

	processResponse: function(args, options, requestUrl) {
		try {
			var req = args[0];
			//		var scripts = req.responseText.extractScripts();
			OOAF.evalScripts(req.responseText);
			var respTxt = req.responseText.stripScripts();
//			var respTxt = "true";
//			alert("*"+respTxt+"*");
			if (respTxt.substr(0, 4) == "true" || respTxt.substr(0, 5) == "false") {
				var jsonargs = respTxt.split('|');
				var boolValue = eval(jsonargs.shift());

				$A(jsonargs).each(function (arg, i) {
					jsonargs[i] = eval("(" + arg + ")");
				});

				if (boolValue) {
					if (options && options.onComplete) {
						jsonargs.unshift(req);
						this.processOnComplete(options.onComplete, jsonargs);
						return true;
					}
				} else {
					if (options && options.onFailure) {
						jsonargs.unshift(req);
						this.processOnComplete(options.onFailure, jsonargs);
						return true;
					} else {
						if (jsonargs.length) {
							logError(jsonargs[0]);
						} else {
							logError(requestUrl + " has returned " + respTxt);
						}
						createLoggingPane(true);
					}
					return false;
				}
			} else {
				breakpoint(function(expr) { return eval(expr); }, "Erreur dans processResponse '"+requestUrl+"'\n"+respTxt, requestUrl);
			}
		} catch (e) {
			alert("OOAF.processResponse: " + e);
		}
	},

	processOnComplete: function(callback, args) {
		try {
			// callback est du code javascript
			eval("var func = " + callback);
			if (typeof (func) == "function") {
				// callback etait en fait une chaine de caratere qui designe un pointeur sur fonction
				func.apply(this, args);
			}
		} catch (e) {
			// callback est un pointeur sur fonction
			if (typeof (callback) == "function") {
				callback.apply(this, args);
			} else {
				alert("OOAF.processOnComplete: Nothing to do" + e);
			}
		}

	}
}

function instanceOf(object, constructorFunction) {
	while (object != null) {
		if (object == constructorFunction.prototype)
		{return true}
		object = object.__proto__;
	}
	return false;
}

var Template = {
	process: function(idTemplate, objBinded) {
		if (!$(idTemplate))
			throw new Error("Template " + idTemplate + " not found");

		return TrimPath.processDOMTemplate(idTemplate, objBinded);
	},

	insert: function(container, where, id, params) {
		container = $(container);
		content = TrimPath.processDOMTemplate(id, params);
		eval('new Insertion.' + where + '(container, content);');
	},

	replace: function(container, id, params) {
		container = $(container);
		content = TrimPath.processDOMTemplate(id, params);
		container.innerHTML = content;
	}
}

var Browser = {
	minimalWin: {dependent:"yes",location:"no",menubar:"no",statusbar:"no"},
	minimalScrollWin: {dependent:"yes",location:"no",menubar:"no",statusbar:"no", resizable:"yes", scrollbars:"yes"},
	completeWin: {dependent:"no",location:"yes",menubar:"yes",statusbar:"yes"},

	isIE: function() {
		if (document.all) {
			return true;
		} else {
			return false;
		}
	},


	getAvailableDimensions: function() {
		if (this.isIE()) {
			return {width:document.body.offsetWidth, height:document.body.offsetHeight};
		} else {
			return {width:window.innerWidth, height:window.innerHeight};
		}
	},

	getInfos: function() {
		var infos = {};
		Object.extend(infos, navigator);

		return infos;
	},

	newWindow: function(url, name, options, extra) {
		if (extra && extra.width && extra.height) {
			options.width = extra.width;
			options.height = extra.height;
			options.left = (screen.width - options.width) / 2;
			options.top = (screen.height - options.height) / 2;
		}

		arrOptions = [];
		for (var i in options) {
			if (typeof options[i] != "function")
			arrOptions.push(i + "=" + options[i]);
		}

		return window.open(url, name, arrOptions.join(","));
	}
}

function show(evt) {
	target = Event.element(evt);
	if (target && target.getAttribute('ooaf_url')) {
		if (target.getAttribute('confirm')) {
			if (confirm(target.getAttribute('confirm'))) {
				processShow(target);
			} else {
				evt.cancelBubble = true;
				return false;
			}
		} else {
			processShow(target);
			evt.cancelBubble = true;
			return false;
		}
	}
}

function processShow(target) {
	var actions = target.getAttribute('ooaf_url').split("|");
	ooafurl = actions[0];
	onready = actions[1];
	if (target.target) {
		view(target.target, ooafurl + '&target=' + target.target, onready);
	} else {
		if (ooafurl.substr(0, 1) == "/") {
			options = {onComplete:onready};
			exec(ooafurl, options);
		} else {
			say(ooafurl, onready);
		}
	}
	if (target.tagName.toUpperCase() == "INPUT") {
		return true;
	} else {
		return false;
	}
}

function exec(eventName, options, postValues) {
	function onCompleteExec(req) {
		OOAF.endRequest();
		OOAF.processResponse(arguments, options, url);
	}

	if (eventName.substr(0, 1) == "/") eventName = eventName.substr(1);
	var url = '/do/'+ eventName + "&ajax=true";
	var ajax = new Ajax.Request(url,
	{
		method:'post',
		requestHeaders:["User-Agent", "OOAF (http://www.eiole.com)",
		'Content-Type', 'application/x-www-form-urlencoded;charset=ISO-8859-1'],
		parameters:postValues,
		onComplete:onCompleteExec
	}
	);
	OOAF.startRequest();
}

/**
* @param mixed $container string|DOMNode
* @params mixed options si string, sera eval apres view sinon peut accepter les valeurs:
* options:
*	- get => array => tableau assoc a passer en $_GET
*	- onComplete => sera ?valu? ou execut?
*   - args si onComplete == function => args sera pass? en params
*/
function view(container, ooafurl, options) {
	container = $(container);
	function onCompleteExec(req) {
		OOAF.endRequest();

		try {
			OOAF.evalScripts(req.responseText);
		} catch (e) {
			breakpoint(function(expr) { return eval(expr); }, "Erreur dans l'eval \nview('"+ container.id +"','"+ooafurl+"', '"+options+"')\n"+req.responseText.extractScripts() , ooafurl);
		}

		if (container) {
			try {
				container.ooafurl = new OOAFUrl(ooafurl);
			} catch (e) {
				container.ooafurl = new Url(ooafurl);
			}
			container.setAttribute('lastview', ooafurl);
		}

		if (options) {
			if (options.debug == true) {
				debugCallback = options.onDebug ? options.onDebug : function(expr) { return eval(expr); };
				breakpoint(debugCallback, "\nview('"+ container.id +"','"+ooafurl+"', '"+options+"')", ooafurl);
			}

			if (typeof(options) == "string") {
				eval(options);
			} else if (options.onComplete) {
				OOAF.processOnComplete(options.onComplete, arguments);
			}
		}
	}

	var params = {
		method:'get',
		requestHeaders:["User-Agent", "OOAF (http://www.eiole.com)"],
		//		evalScripts:true,
		onComplete:onCompleteExec
	};

	if (container) {
		var ajax = new Ajax.Updater(container, ooafurl, params);
	} else {
		var ajax = new Ajax.Request(ooafurl, params);
	}

	OOAF.startRequest();
}

function noop() {return false}

var glTimeOut;

function setDelay(toExec, delay) {
	if (glTimeOut) {
		window.clearTimeout(glTimeOut);
	}
	glTimeOut = window.setTimeout(toExec,delay);
}
