//-----------------------------------------------------------------------

He.OnLoad = function(f)
{
	if(document.loaded === true)
	{
		return f();
	}

	Event.observe(window,'load',f);
};

He.OnDOMReady = function(f)
{
	if(document.loaded === true)
	{
		return f();
	}

	var me = function()
	{
		f();
		document.stopObserving("dom:loaded",me);
	};

	document.observe("dom:loaded",me);
};

He.GetStrObject = function(_obj)
// _place : [in:string] a dot separated list of nodes "He.Components.Etc."
// returns : the object or null
// Usage : He.GetObject("He.Components.SomeThing");
{
	if(!He.IsString(_obj))
	{
		return null;
	}

	if(_obj.substr(0,3) != 'He.')
	{
		_obj = 'He.' + _obj; // Allways Start @ He
	}

	var ret = window;

	_obj = _obj.split('.');
	for(var i = 0; i < _obj.length; ++i)
	{
		var o = _obj[i];

		if(He.IsUndefined(ret[o]))
		{
			return null;
		}

		ret = ret[o];
	}

	return ret;
};

He.Bootstrap('He.Framework.Mail');

He.Framework.Mail.Check = function(_email)
{
	return (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(_email));
};

He.RequireComponent = function(_module)
// _module : [in:string] a path for a javascript module to be loaded
// returns : the module
// Usage : He.RequireComponent('He.Module.Name'); where 'He.' is the Source root.
{
	if(!He.IsString(_module) || _module == '')
	{
		return null;
	}

	if(_module.substr(0,3) != 'He.')
	{
	 	He.Error('Invalid Module : ',_module);
		return null;
	}

	var o = He.GetStrObject(_module);
	if(o !== null)
	{
// 		He.Log('Module Existing : ',_module);
		return o;
	}

	_module = _module.replace(/\./gm,'/');
	_module = '/' + _module + '.js';

// 	He.Log('Loading Module : ',_module);
	He.IncludeJavascript(_module);
};

He.IsStyle = function(_css)
{
	if(!He.IsString(_css) || _css == '')
	{
		return false;
	}

	var head = document.getElementsByTagName("head")[0];
	if(He.IsUndefined(He.Styles))
	{
		He.Styles = {};
		for(var s = 0; s < head.childNodes.length; ++s)
		{
			var se = head.childNodes[s];
			if(se.nodeName.toUpperCase() == 'LINK' && se.rel.toLowerCase() == 'stylesheet')
			{
				se.loaded = true;
				He.Styles[se.href] = se;
			}
		}
	}

	var url = He.Framework.Uri.Parse(_css);
	if(!url.host)
	{
		var base = He.Framework.Uri.Parse(document.location.href);
		_css = base.protocol + '://' + base.authority + _css;
	}

	if(He.IsObject(He.Styles[_css]))
	{
		return He.Styles[_css];
	}

	return _css;
};

He.IncludeStylesheet = function(_css)
// _css : [in:string] an url for a css file to be loaded
// returns : the css element
// Usage : He.IncludeJavacss('url'); where url is a valid url
{
	_css = He.IsStyle(_css);
	if(!He.IsString(_css))
	{
		return _css;
	}

	var css = document.createElement('link');
	var head = document.getElementsByTagName("head")[0];

	css.rel = 'stylesheet';
	css.media = 'screen';
	css.type = 'text/css';
	css.href = _css;

	He.Styles[_css] = css;
	head.appendChild(css);

	return css;
};

He.Bootstrap('He.Scripts');

He.AbsoluteUrl = function(_src)
{
	if(!_src)
	{
		return _src;
	}

	var url = He.Framework.Uri.Parse(_src);
	if(!url.protocol)
	{
		var base = He.Framework.Uri.Parse(document.location.href);

		if(_src.charAt(0) != '/')
		{
			var spath = base.relative.replace(/\/#\//,'').split('/');
			var dpath = _src.replace(/\/#\//,'').split('/');

			while(dpath.length)
			{
				if(dpath[0] == '..')
				{
					spath.pop();
				}
				else
				{
					spath.push(dpath[0]);
				}
				dpath.shift();
			}

			_src = base.protocol + '://' + base.host + '/' + spath.join('/');
		}
		else
		{
			_src = base.protocol + '://' + base.host + _src;
		}
	}
	return _src
}

He.IsScript = function(_script)
{
	if(!He.IsString(_script) || _script == '')
	{
		return false;
	}

	_script = He.Framework.Uri.MakeAbsolute(_script);

	var head = document.getElementsByTagName("head")[0];
	for(var s = 0; s < head.childNodes.length; ++s)
	{
		var se = head.childNodes[s];
		if(se.nodeName.toUpperCase() == 'SCRIPT' && se.type.toLowerCase() == 'text/javascript')
		{
			if(He.IsUndefined(se.loaded))
			{
				se.loaded = true;
			}

			var src = He.Framework.Uri.MakeAbsolute(se.src);
			if(src)
			{
				He.Scripts[src] = se;
			}
		}
	}

	var src = He.Framework.Uri.MakeAbsolute(_script);
	if(He.IsObject(He.Scripts[src]))
	{
		return He.Scripts[src];
	}

	return null;
};

He.IncludeJavascript = function(_script)
// _script : [in:string] an url for a javascript file to be loaded
// returns : the script element
// Usage : He.IncludeJavascript('url'); where url is a valid url
{
	var s = He.IsScript(_script);
	if(He.IsObject(s))
	{
		return s;
	}

	_script = He.Framework.Uri.MakeAbsolute(_script);

// 	He.Log('Loading Script : ',_script);

	var script = document.createElement('script');
	script.type = 'text/javascript';
	script.loaded = false;

	var head = document.getElementsByTagName("head")[0];
	head.appendChild(script);

	He.Scripts[_script] = script;

	var v = He.IncludeJavascript.stack.length;
	He.IncludeJavascript.stack.push(_script);
// 	He.IncludeJavascript.dbg.push(_script);
	if((He.IncludeJavascript.stack.length - v) <= 1)
	{
		He.IncludeJavascript.Next();
	}

	return script;
};

He.IncludeJavascript.stack = [];
He.IncludeJavascript.dbg = [];

He.IncludeJavascript.Next = function()
{
	if(!He.IncludeJavascript.stack.length)
	{
		return;
	}

	var src = He.IncludeJavascript.stack[0];

	var script = He.Scripts[src];

	script.loadcb = function()
	{
		Event.stopObserving(script,'load',script.loadcb);
		script.loadcb = null;
		Event.stopObserving(script,'readystatechange',script.readycb);
		script.readycb = null;

		He.IncludeJavascript.Done(script);
	};
	Event.observe(script,'load',script.loadcb);

	script.readycb = function()
	{
		if(/loaded|complete/.test(this.readyState))
		{
			Event.stopObserving(script,'load',script.loadcb);
			script.loadcb = null;
			Event.stopObserving(script,'readystatechange',script.readycb);
			script.readycb = null;

			He.IncludeJavascript.Done(script);
		}
	}
	Event.observe(script,'readystatechange',script.readycb);

	if(/WebKit/i.test(navigator.userAgent))
	{
		var p = new PeriodicalExecuter(function(pe)
		{
// 		if(/loaded|complete/.test(script.readyState))
			{
				He.IncludeJavascript.Done(script);
				pe.stop();
			}
		}, 3);
	}

	script.src = src;

	return script;
};

He.IncludeSrcName = function(_src)
{
	var src = "";
	if (_src.indexOf("external:") != -1) // Si le script est externe
	{
		return _src.substr(9);
	}
	return He.Framework.Uri.MakeAbsolute('/' + _src.replace(/\./g,'/') + '.js');
};

He.IncludeEvtName = function(_src)
{	// _src waits for an url
	var src = "";
	var uri = He.Framework.Uri.Parse(_src);
	if(uri.host == "" || uri.host == document.location.host)
	{
		src = uri.path || _src;
		if(src)
		{
			src = src.replace(/\.js/,'').replace(/\//g,'.');
			if(src.charAt(0) == '.')
			{
				src = src.substr(1);
			}
		}
	}
	else
	{
		src = (uri.host + uri.path) || _src;
	}
	return 'readyscript:' + src;
}

He.IncludeJavascript.Done = function(_script)
{
	var src = _script.src;
	var n = He.IncludeJavascript.stack.length;
	for(var i = 0; i < n; ++i)
	{
		if(He.IncludeJavascript.stack[i] == src)
		{
			He.IncludeJavascript.stack.splice(i,1);
			He.Scripts[src].loaded = true;

			// Notify
			var event = He.IncludeEvtName(src);
			document.fire(event);

			He.IncludeJavascript.Next();
		}
	}
}

He.WhenReadyCall = function(_event,_cb)
{
	var script = He.IncludeSrcName(_event);
	var event = He.IncludeEvtName(script);

	var script_e = He.IsScript(script);

	if(He.IsObject(script_e) && script_e.loaded === true)
	{
		_cb();
	}
	else
	{
		He.IncludeJavascript(script);

		He.Scripts[script].readycb = function()
		{
			Event.stopObserving(document,event,He.Scripts[script].readycb);
			He.Scripts[script].readycb = null;
			_cb();
		}

		document.observe(event,He.Scripts[script].readycb);
	}
};

//----------------------------------------------------------------------
// He.ClassesHash = {};
// He.DumpClasses = function ()
// {
// 	var elements = $$('*');
// 	var len = elements.length;
// 	for(var i = 0; i < len; ++i)
// 	{
// 		var classes = elements[i].className;
// 		if(classes && classes != '')
// 		{
// 			classes = classes.split(' ');
// 			var clen = classes.length;
// 			for(var j = 0; j < clen; ++j)
// 			{
// 				if(He.IsUndefined(He.ClassesHash[classes[j]]))
// 				{
// 					He.ClassesHash[classes[j]] = [];
// 				}
// 				He.ClassesHash[classes[j]].push(elements[i]);
// 			}
// 		}
// 	}
// // 	He.Log(He.ClassesHash);
// };

// Event.observe(window,'load',He.DumpClasses);

He.GetPageSize = function ()
{
	var xScroll, yScroll;

	if (window.innerHeight && window.scrollMaxY)
	{
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
	}
	else if (document.body.scrollHeight > document.body.offsetHeight)
	{ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	}
	else
	{ // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}

	var windowWidth, windowHeight;

	if (self.innerHeight)
	{	// all except Explorer
		if(document.documentElement.clientWidth)
		{
			windowWidth = document.documentElement.clientWidth;
		}
		else
		{
			windowWidth = self.innerWidth;
		}
		windowHeight = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight)
	{ // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	}
	else if (document.body)
	{ // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}

	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight)
	{
		pageHeight = windowHeight;
	}
	else
	{
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth)
	{
		pageWidth = xScroll;
	}
	else
	{
		pageWidth = windowWidth;
	}

	return [pageWidth,pageHeight];
}

