function getWeek(year,month,day){
    //lets calc weeknumber the cruel and hard way :D
    //Find JulianDay
    month += 1; //use 1-12
    var a = Math.floor((14-(month))/12);
    var y = year+4800-a;
    var m = (month)+(12*a)-3;
    var jd = day + Math.floor(((153*m)+2)/5) +
                 (365*y) + Math.floor(y/4) - Math.floor(y/100) +
                 Math.floor(y/400) - 32045;      // (gregorian calendar)
    //var jd = (day+1)+Math.Round(((153*m)+2)/5)+(365+y) +
    //                 Math.round(y/4)-32083;    // (julian calendar)

    //now calc weeknumber according to JD
    var d4 = (jd+31741-(jd%7))%146097%36524%1461;
    var L = Math.floor(d4/1460);
    var d1 = ((d4-L)%365)+L;
    NumberOfWeek = Math.floor(d1/7) + 1;
    return NumberOfWeek;
}

function DatePicker(client, format)
{
	var self = this;

	this.dateSelected 	= new Date();
	this.today 			= new Date();
	this.client 		= client;
	this.format			= Object.isUndefined(format) ? "#{day}-#{month}-#{year}" : format;
	this.splitString	= null;
	this.partToNum		= {};
	var tmpFormat = '' + this.format;
	var match = tmpFormat.match(/^(.*?)#\{(day|month|year)\}(.*)$/);
	var i = 0;
	while (match) {
		if (match[1] && !this.splitString) {
			this.splitString = match[1];
		}
		this.partToNum[match[2]] = i++;
		tmpFormat = match[3];
		match = tmpFormat.match(/^(.*?)#\{(day|month|year)\}(.*)$/);
	}

	Event.observe(this.client, 'focus', function () { self.checkField(); });
	Event.observe(this.client, 'keyup', function () { self.checkField(); });


	if (this.client.value.length > 0 && this.checkField(this.client.value))
	{
    	/* Set date to the supplied date by input field */
    	dateArray = this.client.value.split(/\D/);
    	this.dateSelected = new Date(dateArray[this.partToNum['year']], (dateArray[this.partToNum['month']] - 1), dateArray[this.partToNum['day']]);
    }

    this.displayDate = new Date(this.dateSelected.getTime());
    /* Remove datePicker */
    this.id = 'datePicker_' + this.client.id;

    if (datePicker = document.getElementById(this.id))
	{
		datePicker.parentNode.removeChild(datePicker);
	}
	else
	{
    	this.render();
    }
}

DatePicker.prototype.checkField = function ()
{
	var value	= this.client.value;
	var result;
	var valid	= true;

	/* Check if the content needs adjusting */
	if (result = value.match(/^\d{1,2}\D\d{1,2}\D\d{4}$/)) {
	} else if (value.length > 0) {
		valid = false;
	}

	this.client.style.borderBottom = valid ? '' : '2px dashed red';
	return valid;
}

DatePicker.prototype.texts = {

     months: [
        PbLib.g('January'), PbLib.g('February'), PbLib.g('March'),
        PbLib.g('April'), PbLib.g('May'), PbLib.g('June'),
        PbLib.g('July'), PbLib.g('August'), PbLib.g('September'),
        PbLib.g('October'), PbLib.g('November'), PbLib.g('December')

     ],
     days: ["M", "D", "W", "D", "V", "Z", "Z"],
     prevMonth: PbLib.g('Previous month'),
     nextMonth: PbLib.g('Next month')
};


DatePicker.prototype.onPrev = function() {

     if ( this.displayDate.getMonth() == 0 ) {
        this.displayDate.setFullYear(this.displayDate.getFullYear() - 1);
        this.displayDate.setMonth(11);
     } else {
        this.displayDate.setDate(1);
     	this.displayDate.setMonth(this.displayDate.getMonth() - 1);
     }
     this.render();
}

DatePicker.prototype.onNext = function() {

     if ( this.displayDate.getMonth() == 11 ) {
        this.displayDate.setFullYear(this.displayDate.getFullYear() + 1);
        this.displayDate.setMonth(0);
     } else {
        // Set first to first day of month because it otherwise goes wrong with the 31th of a month
     	this.displayDate.setDate(1);
     	this.displayDate.setMonth(this.displayDate.getMonth() + 1);
     }
     this.render();
}

DatePicker.prototype.onMonth = function() {

	d = new Date();
	this.displayDate = d;
	this.render();
}

DatePicker.prototype.onDay = function(day) {

	this.client.focus();
	day = parseInt(day.innerHTML);
	if ( day > 0 )
	{	this.dateSelected = this.displayDate;
		this.dateSelected.setDate(day);
        this.client.value = this.format.interpolate({
        	'day': this.dateSelected.getDate(),
        	'month': (this.dateSelected.getMonth() + 1),
        	'year': this.dateSelected.getFullYear()});
        this.checkField();
    }

	this.hide();
}

DatePicker.prototype.onYear = function(year) {

	year = parseInt(year.value);
	if ( year > 0 )
	{
		this.displayDate.setYear(year);
    }

	this.render();
}

DatePicker.prototype.hide = function(day) {

	if (datePicker = document.getElementById(this.id))
	{
		datePicker.parentNode.removeChild(datePicker);
	}
}

DatePicker.prototype.getYearSelect = function() {

	var self = this;
	var selYear = document.createElement('select');
	selYear.onchange = function()
		{
			self.onYear(selYear.options[selYear.selectedIndex]);
		}

	var curYear = this.displayDate.getFullYear();

	var option,txt;
	for (var i = curYear - 10; i < curYear + 10; i++)
	{
		option = document.createElement("option");
		selYear.options.add(option);
		if (i == (curYear - 10)) {
			txt = '<<<';
			option.value = i - 8;
		} else if (i == (curYear + 9)) {
			txt = '>>>';
			option.value = i + 9;
		} else {
			txt = i;
			option.value = i;
		}
		txt = document.createTextNode(txt);
		option.appendChild(txt);

		if (curYear == i)
		{	option.selected = 'selected';
		}
	}

	return selYear;
}

DatePicker.prototype.getMonthSelect = function() {

	if (datePicker = document.getElementById(this.id))
	{
		datePicker.parentNode.removeChild(datePicker);
	}
}

function startHover(elem, num, interval)
{
	elem.parentNode.timeout = window.setInterval("addOptions(document.getElementById('" + elem.parentNode.id + "'), '" + elem.value + "', '" + num + "');", interval);
}
function stopHover(elem)
{
	if (elem.parentNode.timeout) {
		window.clearInterval(elem.parentNode.timeout);
		elem.parentNode.timeout = null;
	}
}
function addOptions(elem, direction, numElems)
{
	var temp;
	if (direction == 'up') {
		var target		= elem.firstChild.nextSibling;
		var startVal	= parseInt(target.value);
		for (var i = numElems; i > 0; i--) {
			temp = elem.insertBefore(document.createElement('option'), target);
			temp.value = startVal - i;
			temp.appendChild(document.createTextNode(startVal - i));

			elem.removeChild(elem.lastChild.previousSibling);
		}
	} else {
		var target		= elem.lastChild;
		var startVal	= parseInt(target.previousSibling.value);
		for (var i = 1; i <= numElems; i++) {
			temp = elem.insertBefore(document.createElement('option'), target);
			temp.value = startVal + i;
			temp.appendChild(document.createTextNode(startVal + i));

			elem.removeChild(elem.firstChild.nextSibling);
		}
	}
}

DatePicker.prototype.render = function() {

	var oT, oTR, oTH, oTD, oTxt;
	var self = this;
	this.hide();


	oT = document.createElement('table');
	oT.id = 'datePicker_' + this.client.id;
	oT.className = 'datePicker';
	oT.border = 1;
	oT.style.position = 'absolute';

	/* Generate dates */
	var d = new Date(this.displayDate.getTime());
	var m = d.getMonth();
	var dPrev = new Date(d.getTime());

	/* Generate previous month */
	dPrev.setDate(0);
	day = dPrev.getDate();

	oTR = oT.insertRow(oT.rows.length);
	for (i = dPrev.getDay() - 1; i >= 0 ; i--)
	{
		if (i == dPrev.getDay() -1)
		{
			oTR = oT.insertRow(oT.rows.length);
			oTD = oTR.insertCell(oTR.cells.length);
			oTD.className = 'week';
			oTxt = document.createTextNode(getWeek(dPrev.getFullYear(), dPrev.getMonth(), dPrev.getDate()));
			oTD.appendChild(oTxt);
		}

		oTD = oTR.insertCell(oTR.cells.length);
		oTxt = document.createTextNode(day - i);
		oTD.appendChild(oTxt);
		//oTD.onclick = function () { self.onDay(this); }
		//oTD.onmouseover = function () { this.className = 'curMonthHover'; };
		//oTD.onmouseout 	= function () { this.className = 'othMonth'; };
		oTD.className = 'othMonth';
	}

	/* Generate current month */
	for (i = 1, d.setDate(i); d.getMonth() == m; i++, d.setDate(i))
	{
		if (d.getDay() == 1) {
			oTR = oT.insertRow(oT.rows.length);
			oTD = oTR.insertCell(oTR.cells.length);
			oTD.className = 'week';
			oTxt = document.createTextNode(getWeek(d.getFullYear(), d.getMonth(), d.getDate()));
			oTD.appendChild(oTxt);
		}

		oTD = oTR.insertCell(oTR.cells.length);
		oTD.className = 'curMonth';
		oTxt = document.createTextNode(d.getDate());
		oTD.appendChild(oTxt);
		oTD.onmouseover = function () { this.className = 'curMonthHover'; };
		oTD.onmouseout 	= function () { this.className = 'curMonth'; };
		if ((d.getDate() == this.dateSelected.getDate()) && (d.getMonth() == this.dateSelected.getMonth()) && (d.getYear() == this.dateSelected.getYear()))
		{
			oTD.id = 'selDate';
		}
		if ((d.getDate() == this.today.getDate()) && (d.getMonth() == this.today.getMonth()) && (d.getYear() == this.today.getYear()))
		{
			oTD.className = 'curDay';
			oTD.onmouseover = function () { this.className = 'curDayHover'; };
			oTD.onmouseout 	= function () { this.className = 'curDay'; };
		}

		oTD.onclick = function () { self.onDay(this); }
	}

	/* Generate next month */
	for (i = 1; oTR.cells.length < 8; i++)
	{
		oTD = oTR.insertCell(oTR.cells.length);
		oTxt = document.createTextNode(i);
		oTD.appendChild(oTxt);
		//oTD.onclick = function () { self.onDay(this); }
		//oTD.onmouseover = function () { this.className = 'curMonthHover'; };
		//oTD.onmouseout 	= function () { this.className = 'othMonth'; };
		oTD.className = 'othMonth';
	}

	/* Generate Thead */
	oTH = oT.createTHead();

	oTR = oTH.insertRow(oTH.rows.length);

	oTD = oTR.insertCell(oTR.cells.length);
	oTxt = document.createTextNode(this.texts.months[this.displayDate.getMonth()] + ' ');
	oTD.appendChild(oTxt);
	oTD.appendChild(this.getYearSelect());
	oTD.className = 'curMonthYear';
	oTD.colSpan='5';

	oTD = oTR.insertCell(oTR.cells.length);
	oTD.className = 'navButtons';
	oTD.onmouseover = function () { this.className = 'navButtonsHover'; };
	oTD.onmouseout 	= function () { this.className = 'navButtons'; };
	oTD.onclick = function() { self.onPrev(); }

	oImg = document.createElement('img');
	oImg.src = PbLib.getNewURI('ui/uibase/img/dateChooserArrow_left.gif');
	oTD.appendChild(oImg);

	oTD = oTR.insertCell(oTR.cells.length);
	oTD.className = 'navButtons';
	oTD.onmouseover = function () { this.className = 'navButtonsHover'; };
	oTD.onmouseout 	= function () { this.className = 'navButtons'; };
	oTD.onclick = function() { self.onNext(); }

	oImg = document.createElement('img');
	oImg.src = PbLib.getNewURI('ui/uibase/img/dateChooserArrow_right.gif');
	oTD.appendChild(oImg);

	oTD = oTR.insertCell(oTR.cells.length);
	oTD.className = 'navButtons';
	oTD.onmouseover = function () { this.className = 'navButtonsHover'; };
	oTD.onmouseout 	= function () { this.className = 'navButtons'; };
	oTD.onclick = function() { var picker = document.getElementById(self.id); picker.parentNode.removeChild(picker); }

	oImg = document.createElement('img');
	oImg.src = PbLib.getNewURI('ui/uibase/img/dateChooserRemove.gif');
	oTD.appendChild(oImg);

	oTR = oTH.insertRow(oTH.rows.length);
	oTD = oTR.insertCell(oTR.cells.length);
	oTxt = document.createTextNode('Week');
	oTD.appendChild(oTxt);
	for (var i = 0; i < 7; i++)
	{
		oTD = oTR.insertCell(oTR.cells.length);
		oTxt = document.createTextNode(this.texts.days[i]);
		oTD.appendChild(oTxt);
	}

	/* Generate TFoot */
	oTF = oT.createTFoot();
	oTR = oTF.insertRow(oTF.rows.length);
	oTD = oTR.insertCell(oTR.cells.length);
	oTxt = document.createTextNode(PbLib.g('This month'));
	oTD.appendChild(oTxt);
	oTD.colSpan='8';
	oTD.onmouseover = function () { this.className = 'navButtonsHover'; };
	oTD.onmouseout 	= function () { this.className = 'curMonth'; };
	oTD.onclick = function() { self.onMonth(); }
	oTD.className = 'thisMonth';

	var pos = ProBaseObject.prototype.getPos(this.client);
	oT.style.left = pos[0] + 'px';
	oT.style.top = pos[1] + this.client.offsetHeight + 'px';
	document.body.appendChild(oT);
}