﻿function $func(func)
{
	if(typeof(func) == "function") return func;
	var args = Array.prototype.slice.call(arguments);
	var body = args.shift();
	var result = null;
	if(args.length > 0)
	{
		fargs = ["'" + args[0] + "'"];
		for(var n = 1; n < args.length; n++)
		{
			fargs.push("'" + args[n] + "'");
		}
		result = new Function(fargs.toString(), body);
	}
	else
		result = new Function(body);
	return result;
}
function Using(namespace, path)
{
	//Test if we have already loaded this namespace.
	if (Using[namespace.toLowerCase()])return;
	
	//Load Namespace.
	path = path || Window.JavascriptPath || "";
	var script  = document.createElement("script");
	script.type = "text/javascript";
	script.src  = path + namespace + ".js";
	document.body.insertBefore(script, document.body.firstChild);
	
	//Mark this namespace has loaded.
	Using[namespace.toLowerCase()] = true;
}

//Make a name more C# Like ;-)
ArrayList = Array;
ArrayList.prototype.CheckType = function(value)
{
	if (!this.BaseType)return;
	switch (this.BaseType)
	{
		case String:
			if (typeof(value) == "string")return;
			throw "Invalid Type"

		case Number:
			if (typeof(value) == "number")return;
			throw "Invalid Type"

		default:
			if (value instanceof this.BaseType)return;
			throw "Invalid Type"
	}
}
ArrayList.prototype.Add = function(value)
{
	this.CheckType(value);
	var index = this.length;
	this[index] = value;
	return index;
}
ArrayList.prototype.AddRange = function(array)
{
	for(var i = 0; i < array.length; i++)
	{
		this.Add(array[i]);
	}
}
ArrayList.prototype.Remove = function(value)
{
	var index= this.IndexOf(value);
	if (index != -1)
	{
		this.RemoveAt(index);
	}
}
ArrayList.prototype.RemoveAt = function(index)
{
	this.splice(index, 1);
}
ArrayList.prototype.RemoveRange = function(index, count)
{
	this.splice(index, count);
}
ArrayList.prototype.IndexOf = function(value)
{
	for(var i = 0; i < this.length; i++)
	{
		if (this[i] == value)
		{
			return i;
		}
	}
	return -1;
}
ArrayList.prototype.LastIndexOf = function(value)
{
	for(var i = this.length - 1; i >= 0; i--)
	{
		if (this[i] == value)
		{
			return i;
		}
	}
	return -1;
};
ArrayList.prototype.Contains = function(value)
{
	return this.IndexOf(value) != -1;
}
ArrayList.prototype.GetRange = function(index, count)
{
	return this.slice(index, index + count);
}
ArrayList.prototype.Insert = function(index, value)
{
	this.CheckType(value);
	this.splice(index, 0, value);
}
ArrayList.prototype.InsertRange = function(index, array)
{
	for(var i = 0; i < array.length; i++)
	{
		this.Insert(index + i, array[i]);
	}
}
ArrayList.prototype.Clear = function()
{
	this.splice(0, this.length);
}
ArrayList.prototype.Clone = function()
{
	return this.slice(0, this.length);
}
ArrayList.Repeat = function(value, count)
{
	var result = [];
	for(var i = 0; i < count; i++)
	{
		result[i] = value;
	}
	return result;
}


//Update String Methods.
// Mis en commentaire car chrome n'aime pas la surchage du ToString
/*String.prototype._toString = String.prototype.toString;*/
String.prototype.ToString = function(formating)
{
	if (/^json$/i.test(formating))
	{
		return this.ToJson();
	}
	else
	{
		return this;
	}
};
/*String.prototype.ToString = String.prototype.toString;*/
String.prototype.IndexOf = String.prototype.indexOf;
String.prototype.Replace = String.prototype.replace;
String.prototype.Trim = function()
{
	return this.Replace(/^\s*((.|\s)+?)\s*$/g, "$1");
}
String.prototype.LTrim = function()
{
	return this.Replace(/^\s*((.|\s)+?)$/g, "$1");
}
String.prototype.RTrim = function()
{
	return this.Replace(/^((.|\s)+?)\s*$/g, "$0");
}
String.prototype.ToJson = function()
{
	return "\"" +
		this.Replace(/("|\r?\n|\\)/g, function(match)
		{
			switch (match)
			{
				case '"':    return "\\\"";
				
				case "\n":
				case "\r\n": return "\\n";
				
				case "\\":   return "\\\\";
			}
		}) + "\""; 
		
}
String.Format = function(template, parameters)
{
	var formatArguments  = String.Format.arguments;
	
	var globalExpression = /\{(\d+)(?:\:(.+?))?\}/g;
	var localExpression  = /\{(\d+)(?:\:(.+?))?\}/;
	return template.replace(globalExpression, function (match)
	{
		match = localExpression.exec(match);
		var index     = parseInt(match[1], 10) + 1;
		var formating = match[2];
		var object    = formatArguments[index];
		if (object == null)
		{
			return String.Empty;
		}
		if (object.ToString)
		{
			return object.ToString(formating);
		}
		return object.toString(formating);
	});
}
String.Empty = "";

Number.MinLength = function(value, length)
{
	value = value + "";
	while (value.length < length)
	{
		value = "0" + value;
	}
	return value;
};
Number.prototype.ToString = Number.prototype.toString;

DateTime = Date;
DateTime.Today = new Date();
DateTime.Today = new Date(DateTime.Today.getFullYear(), DateTime.Today.getMonth(), DateTime.Today.getDate());
DateTime.prototype._toString = DateTime.prototype.toString;
DateTime.prototype.GetFormatTemplate   = function(formating)
{
	switch (formating)
	{
		case "d": return "MM/dd/yyyy";
		case "D": return "dddd, MMMM dd, yyyy";
		case "f": return "dddd, MMMM dd, yyyy HH:mm";
		case "F": return "dddd, MMMM dd, yyyy HH:mm:ss";
		case "g": return "dd/MM/yyyy HH:mm";
		case "G": return "dd/MM/yyyy HH:mm:ss";
		case "m": return "MMMM dd";
		case "r": return this.toGMTString();
		case "s": return "yyyy-MM-ddTHH:mm:ss";
		case "t": return "HH:mm";
		case "T": return "HH:mm:ss";
		case "u": return "yyyy-MM-dd HH:mm:ssZ";
		case "U": return "dddd, MMMM dd, yyyy HH:mm:ss";
		case "y": return "MMMM, yyyy";
		default:  return formating;
	}
};
DateTime.prototype.ToString  = function(formating)
{
	formating = formating || "G";
	var othis = this;
	formating = this.GetFormatTemplate(formating);
	return formating.replace(/(dddd|ddd|dd|MMMM|MMM|MM|yyyy|HH|mm|ss)/g, function(datePart)
	{
		switch (datePart)
		{
			//paterns
			case "dd"  : return Number.MinLength(othis.getDate(),      2);
			case "ddd" : return DateTime.Days[MultilingualHelper.CurrentUserLanguage][othis.getDay()];
			case "dddd": return DateTime.FullDays[MultilingualHelper.CurrentUserLanguage][othis.getDay()];
			case "MM"  : return Number.MinLength(othis.getMonth() + 1, 2);
			case "MMM" : return DateTime.Months[MultilingualHelper.CurrentUserLanguage][othis.getMonth()];
			case "MMMM": return DateTime.FullMonths[MultilingualHelper.CurrentUserLanguage][othis.getMonth()];
			case "yyyy": return Number.MinLength(othis.getFullYear(),  4);
			case "HH"  : return Number.MinLength(othis.getHours(),     2);
			case "mm"  : return Number.MinLength(othis.getMinutes(),   2);
			case "ss"  : return Number.MinLength(othis.getSeconds(),   2);
			
			//Unknown...
			default    : return match;
		}
	});
};
DateTime.prototype.ToJson = function()
{
	if ((this.getHours() == 0) && (this.getMinutes() == 0) && (this.getSeconds() == 0))
	{
		return String.Format("new Date({0},{1},{2})", this.getFullYear(), this.getMonth(), this.getDate());
	}
	else
	{
		return String.Format("new Date({0},{1},{2},{3},{4},{5})", this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds());
	}
};
DateTime.prototype.toString = DateTime.prototype.ToString;
DateTime.FullDays           = {};
DateTime.Days               = {};
DateTime.FullMonths         = {};
DateTime.Months             = {};
DateTime.FullDays["fr"]     = ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"];
DateTime.Days["fr"]         = ["Dim.", "Lun.", "Mar.", "Mer.", "Jeu.", "Ven.", "Sam."];
DateTime.FullMonths["fr"]   = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
DateTime.Months["fr"]       = ["Jan.", "Fév.", "Mars", "Avr.", "Mai", "Juin", "Jui.", "Août", "Sept.", "Oct.", "Nov.", "Déc."];

DateTime.FullDays["nl"]     = ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"];
DateTime.Days["nl"]         = ["Zon.", "Maa.", "Din.", "Woe.", "Don.", "Vri.", "Zat."];
DateTime.FullMonths["nl"]   = ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"];
DateTime.Months["nl"]       = ["Jan.", "Feb.", "Maa.", "Apr.", "Mei", "Juni", "Juli", "Aug.", "Sep.", "Okt.", "Nov.", "Dec."];

DateTime.FullDays["en"]     = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
DateTime.Days["en"]         = ["Sun.", "Mon.", "Tue.", "Wed.", "Thu.", "Fri.", "Sat."];
DateTime.FullMonths["en"]   = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
DateTime.Months["en"]       = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June", "July", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."];

function Uri(uriString)
{
	this.UriString = uriString || window.location.toString();
}

Uri.prototype.ToString = function()
{
	return this.UriString;
}
Uri.prototype.toString = Uri.prototype.ToString;
Uri.prototype.MakeRelative = function(uri)
{
	//Validation
	if (!uri)
	{
		throw "Argument Null: uri";
	}
	if (!(uri instanceof Uri))
	{
		throw "Invalid Type: uri";
	}
	var url1 = this.UriString.split("/");
	var url2 = uri.UriString.split("/");
	var maxCommon = 0;
	while (url1[maxCommon].toLowerCase() == url2[maxCommon].toLowerCase())
	{
		maxCommon++;
	}
	url1.splice(0, maxCommon);
	url2.splice(0, maxCommon);
	var result = url2.join("/");
	if (result == uri.UriString)
	{
		return result;
	}
	for(var i = 1; i < url1.length; i++)
	{
		result = "../" + result;
	}
	return result;
}


function EventArgs()
{
}
EventArgs.Empty = new EventArgs();

function AddEventListener(item, eventName, handler)
{
	if (window["addEventListener"])
	{//Standard
		item.addEventListener(eventName, handler, true);
	}
	else
	{//IE
		item.attachEvent("on" + eventName, handler);
	}
}

/*System.Delegate*/
function Delegate(method, target)
{
	var result = function()
	{
		var res;
		var script = "";
		for (var i = 0; i < result.InvocationList.length; i++)
		{
			var method = "res = result.InvocationList[" + i +"].Method.call(result.InvocationList[" + i +"].Target";
			for(var j = 0; j < result.arguments.length; j++)
			{
				method += ", result.arguments[" + j + "]";
			}
			method += ");"
			script += method;
		}
		eval(script);
		return res;
	};
	result.InvocationList = [];
	if (method)
	{
		result.InvocationList.Add({Method: method, Target:target});
	}
	result.Add = function(delegate)
	{
		if (!delegate)return;
		if (delegate.IsDelegate)
		{
			result.InvocationList.AddRange(delegate.InvocationList);
		}
		else if (typeof(delegate) == "function")
		{
			result.InvocationList.Add({Method: delegate});
		}
	};
	result.Remove = function(delegate)
	{
		for (var i = 0; i < delegate.InvocationList.length; i++)
		{
			result.InvocationList.Remove( delegate.InvocationList[i] );
		}
	};
	result.IsDelegate = true;
	return result;
}
if (typeof(MultilingualHelper) != "object")
{
	MultilingualHelper = {CurrentUserLanguage: "fr"};
}
