//<!--Copyright 2006,2007 Eljakim Information Technology B.V.-->
//Parsing and rendering Javascript Dates

//for the date renderer:
var months	   = new Array("jan","feb","mar","apr","mei","jun","jul","aug","sep","okt","nov","dec");
var longMonths = new Array("januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december");
var days       = new Array("ma","di","wo","do","vr","za","zo");
var longDays   = new Array("maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag");



function findVal(array,input)
{
	for(var i=0;i<array.length;i++)
	{
		if(input==array[i])return true;
	}
	return false;
}

function fixInt(input) //als een nummer met nullen begint halen we de nullen weg zodat parseint ermee overweg kan
{
		input = input + "";
		var chr = "0";
		var i = 0;
		while(chr == "0" && i<input.length)
		{
			chr = input.substr(i,1);
			i++;
		}

		if(i<=input.length)
		{
			return input.substring(i-1);
		}else
			return "0";
}

function fixDateLength(date)
{
	date +="";
	if(date.length<2)
		return 0 +""+ date;
	else
		return date;
}
function DateParser(format, date)
{
	this.regExp = '';
	this.regExpBackup = new RegExp('\\D+');
	this.format = format;
	this.dateString = date;
	this.renderAr = new Array();
	this.formatAr = new Array();
	this.months = new Array("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
	this.types = new Array("d","m","y","n","h","i","s","w");
	//this.formatAr = new Array();
	this.parseFormat();
	var reString = this.formatAr.join("|");
	//alert(reString);
	this.regExp = new RegExp(reString);	
	//this.dateAr = date.split(this.sep);
}
DateParser.prototype.parseFormat = function()
{
	//builds regular expression to split at correct points
	var sep = "";
	var skip = false;
	for(var i=0;i<this.format.length;i++)
	{
		var ch = this.format.substr(i,1);
		// \ is escape char
		if(ch=="\\" &&!skip){skip=true;continue;}	
		//if current char is a format char from the types array we make a split point
		if(findVal(this.types,ch.toLowerCase()) && !skip)
		{
			//is used for parsing
			if(sep)
				this.formatAr[this.formatAr.length] = sep;
			//is used for rendering
			this.renderAr[this.renderAr.length] = sep;
			this.renderAr[this.renderAr.length] = ch;
			sep = "";
		}
		else //otherwise the char isn't a format char but just layout --> save it to use as seperator
		{
			sep+=ch;
		}
		skip = false;
	}
}


DateParser.prototype.parse = function(date)
{
		if(date)this.dateString = date;
		if(!this.dateString)return "";
		this.date = new Date();
		//the defaults when certain bits cant be parsed
		this.tempdate = {	d:this.date.getDate(),
							m:this.date.getMonth(),
							y:this.date.getFullYear(),
							h:0,
							s:0,
							i:0
						};

		var dateAr = this.dateString.split(this.regExp);
		var typeAr = this.format.split(this.regExp);
		//if split didnt work just try to split at chars that are not numeric
		if(dateAr.length <=1)
			dateAr = this.dateString.split(this.regExpBackup);
		//if that didnt work as well just split on 2 chars (so 220807 will be interperted as 22-08-2007)
		if(dateAr.length <=1)
			dateAr = [this.dateString.substr(0,2),this.dateString.substr(2,2),this.dateString.substr(4)];
		
		this.setMonth = false;
		for(var i=0;i<dateAr.length && i<typeAr.length;i++)
		{
			var format  = typeAr[i].toLowerCase();
			var datestr = dateAr[i].toLowerCase();
			//calling the correct parserfunction from the convertDate object/hashtable thingy, long live javascript ;-)
			var datepart = convertDate[format](datestr); //is like convertDate.y(datestr);
			if(!isNaN(datepart))
				this.tempdate[format] = datepart;
		}
		this.date = new Date(this.tempdate.y,this.tempdate.m,this.tempdate.d,this.tempdate.h,this.tempdate.i,this.tempdate.s);
		if(!isNaN(this.date.valueOf()))
			return this.date;
		else
			return new Date();
}

//default function to parse the date string
var defaultConvert = function(date){
										//for most datestrings this is sufficcient (like number of the month)
										if(date.length>2)date = date.substring(0,2);
										date = parseInt(fixInt(date));
										return date;
}
//object/hashtable to determine which function to call for which datestring
var convertDate = {
				"h" : defaultConvert,
				"i" : defaultConvert,
				"s" : defaultConvert,
				"d" : defaultConvert,
				"y" : function(date){
										if(date.length == 0) return NaN;
										if(date.length == 1) date = "0" + date;
										if(date.length < 4 && date<"50")date="20"+date;
										if(date.length < 4 && date>"50")date="19"+date;
										if(date.length > 4)date = date.substring(0,4);
										date = parseInt(fixInt(date));
										return date;
									},
				"m" : function(date){
										if(date.length>2)date = date.substring(0,2);
										date = parseInt(fixInt(date))-1;
										return date;
									},
				"n" : function(date){
										var tempDate = date.substring(0,3);
										if(tempDate=="mei")tempDate="may"; //om nederlands te ondersteunen
										if(tempDate=="maa")tempDate="mar"; //om nederlands te ondersteunen
										for(var j=0;j<this.months.length;j++) //checken op de eerste 3 letters van de maand
										{
											if(this.months[j] == tempDate)
												return j;
										}
										for(var j=0;j<this.months.length;j++) //als er niets op drie letters gevonden is, kijk dan naar de eerste letter
										{
											if(this.months[j].substring(0,1) == tempDate.substring(0,1))
												return j;
										}
										return 0;
									}
};

//======================================================================================================================================================

function DateRenderer(format,date)
{
	this.format = format;
	this.date = date;
	this.renderAr = new Array();
	this.formatAr = new Array();
	this.types = new Array("d","m","y","n","h","i","s","w");
	this.functions = {"d" : "getDate","m":"getMonth","y":"getFullYear","n":"getMonth","h":"getHours","i":"getMinutes","s":"getSeconds","w":"getDay"};
	this.parseFormat();
}

DateRenderer.prototype.parseFormat = DateParser.prototype.parseFormat;

DateRenderer.prototype.render = function(date)
{
	if(date)this.date = date;
	if(!this.date) return "";
	var outputDate = "";
	for(var i=0;i<this.renderAr.length;i++)
	{	if(this.renderAr[i].toLowerCase() in this.functions)
		{
			//calls the correct funtions to render the date part
			var functionname = this.functions[this.renderAr[i].toLowerCase()];
			var datepart = this.date[functionname]();
			outputDate += "" + renderDate[this.renderAr[i]](datepart);
		}
		else
			outputDate += this.renderAr[i];
	}
	return outputDate;
}

var defaultRenderLowerCase = function(date){
	return date;
}
var defaultRenderUpperCase = function(date){
	return fixDateLength(date);
}

var renderDate = {
		"y" : function(date){return date.substr(2,date.length);},
		"Y"	: defaultRenderUpperCase,
		"d"	: defaultRenderLowerCase,
		"D"	: defaultRenderUpperCase,
		"m"	: function(date){return date+1;},
		"M"	: function(date){return fixDateLength(date+1);},
		"h"	: defaultRenderLowerCase,
		"H"	: defaultRenderUpperCase,
		"i"	: defaultRenderLowerCase,
		"I"	: defaultRenderUpperCase,
		"s"	: defaultRenderLowerCase,
		"S"	: defaultRenderUpperCase,
		"n"	: function(date){return months[date];},
		"N"	: function(date){return longMonths[date];},
		"w"	: function(date){return days[date-1];},
		"W"	: function(date){return longDays[date-1];}
};

//===================================================================================================================

//====Numeric Parser
function NumericParser(separator, value)
{
	this.value = value + "";
	this.separator = separator;
	this.re = new RegExp("[^\\-\\d\\"+separator+"]", "ig");
}
NumericParser.prototype.parse = function ()
{
	this.value+="";
	this.value = this.value.replace(this.re,""); //haal alles weg behalve de getallen en de seperator
	this.value = this.value.replace(this.separator,"."); //vervang de separator door een punt, daar kan parseFloat mee overweg
	return parseFloat(fixInt(this.value));
}

//=====Numeric renderer
function NumericRenderer(separator, separator2, decimals, value)
{
	this.separator = separator;
	this.separator2 = separator2;
	this.decimals = decimals;
	this.value =value;
}
NumericRenderer.prototype.render = function ()
{
	this.handleDecimals();
	this.handleSeparator();
	return this.value;
}

NumericRenderer.prototype.handleDecimals = function()
{
	//adding decimals like 523,7800
	//rounding
	var dec = Math.pow(10,this.decimals);
	this.value = Math.round(this.value*dec)/dec;
	//string convert
	this.value+="";
	//building tupel: 34.25 ==> [34,25]
	var tupel = this.value.split(".");
	if(tupel.length<2 && this.decimals>0)tupel[tupel.length]="";
	//adding zero's to match number of decimals
	while(tupel[tupel.length-1].length<this.decimals)
	{
		tupel[tupel.length-1] +="0";
	}
	this.tupel = tupel;
}

NumericRenderer.prototype.handleSeparator = function()
{
	//function for adding thousand separator like 100.000.000
	var number = this.tupel[0].split("");
	if(number.length == 0)
		number[0] = "0";
	
	//grouping number value in groups of three characters
	var counter = 1;
	
	//making sure we dont get things like .100.000 or -.100.000
	var stop = 1;
	//if the number is negative
	if(number[0]=="-")stop=2;
	
	//looping over the number(in reverse order) and add a separator every 3 chars
	for(var i=number.length-1;i>=stop;i--)
	{
		if(counter>2)
		{
			//adding the separator
			number.splice(i,0,this.separator2);
			counter = 0;
		}
		counter++;
	}
	
	//wrapping things up
	number = number.join("");
	this.tupel[0] = number;
	this.value = this.tupel.join(this.separator);	
}
