//	written	by Tan Ling	Wee	on 2 Dec 2001
//	last updated 10 Oct 2007
//	email : fuushikaden@yahoo.com
//	website : www.pengz.com
//	TabSize: 4
//
//	modified by Mila76 10 Oct 2007    - object oriented and "prototyped".
//									  - css support
//									  - removed holiday support
//									  - removed paste
//									  - remove week number
//	email: mila76@mila76.it
//
//	modified by Mila76 26 May 2004    - italian language included.
//									  - bug fixing
//
//	modified by ALQUANTO 30 July 2003 - german language included.
//									  - modified languageLogic with the ISO-2letter-strings
//									  - changes in in showCalendar: defaultLanguage is already set...
//									  - js and html corrected... more xhtml-compliant... simplier css
//	email: popcalendar@alquanto.de
//
//	modified by PinoToy 25 July 2003  - new logic for multiple languages (English, Spanish and ready for more).
//									  - changes in popUpMonth & popDownMonth methods for hidding	popup.
//									  - changes in popDownYear & popDownYear methods for hidding	popup.
//									  - new logic for disabling dates in	the past.
//									  - new method showCalendar, dynamic	configuration of language, enabling	past & position.
//									  - changes in the styles.
//	email  : pinotoy@yahoo.com

if (typeof Prototype == 'undefined')
  alert('Calendar Error: Prototype could not be found. Please make sure that your application layout includes prototype.js');

var popCalendar = {
	initialize: function(element, options) {
		this.options = Object.extend({
	      language: 'it',    // Default Language: en - english ; es - spanish; de - german ; it - italian
	      startAt: 1,        // 0 - sunday ; 1 - monday
	      showToday: 1,      // 0 - don't show; 1 - show
	      format: 'dd/mm/yyyy',
	      onDateClick: null
	    }, options || {});
		
		this.element = $(element);
		
		this.setStrings();

		var now = new Date();
		this.today = {
			day: now.getDay(),
			date: now.getDate(),
			month: now.getMonth(),
			year: now.getFullYear()
		};
		
		this.dateSelected = Object.clone(this.today);
		
		if ($('popcalendar'))
			this.calendar = $('popcalendar');
		else
			this.createCalendarBase();

		this.eventCloseKey = this.closeOnKey.bindAsEventListener(this);
		this.eventCloseClick = this.closeOnClick.bindAsEventListener(this);
		Event.observe(document, 'keydown', this.eventCloseKey);
		Event.observe(document, 'mousedown', this.eventCloseClick);

		this.popUpCalendar();
	},

	createCalendarBase: function() {
		this.calendar = new Element('div', {id: 'popcalendar', className: 'popcalendar'});
		this.calendar.hide();
		
		var calendarHTML = '<div class="cds_header"><a href="#" id="prevmonth"></a><a href="#" id="nextmonth"></a><span id="spanmonthyear"></span></div>';
		calendarHTML += '<div class="cds_body" style="clear: left;" id="content"></div>';
		if (this.options.showToday == 1) calendarHTML += '<div class="cds_buttons">' + this.todayString[this.options.language] + ' <a id="lblToday" title="' + this.gotoString[this.options.language]+'" href="#">'+this.dayName[this.options.language][(this.today.day % 7)]+', ' + this.today.date + ' ' + this.monthName[this.options.language][this.today.month].substring(0,3) + ' ' + this.today.year + '</a></div>';
		calendarHTML += '<div id="selectmonthyear" style="display:none;"></div>';

		this.calendar.innerHTML = calendarHTML
		document.body.appendChild(this.calendar);
		
		this.selectmonthyear = $('selectmonthyear');
		
		$('prevmonth').observe('click', this.decMonth.bindAsEventListener(this));
		$('nextmonth').observe('click', this.incMonth.bindAsEventListener(this));
		$('lblToday').observe('click', function(event) {
			Event.stop(event);
			
			this.dateSelected.month = this.today.month;
			this.dateSelected.year = this.today.year;
			this.constructCalendar();
		}.bindAsEventListener(this));
		$('spanmonthyear').observe('click', this.popUpYear.bind(this));
	},
	
	hideCalendar: function() {
		Event.stopObserving(document, 'keydown', this.eventCloseKey);
		Event.stopObserving(document, 'click', this.eventCloseClick);
		
		this.popDownYear();
		this.calendar.hide();
	},
	
	closeOnKey: function(event) {
		if (event.keyCode == Event.KEY_ESC) this.hideCalendar();
	},

	closeOnClick: function(event) {
		if (!$(Event.element(event)).descendantOf(this.calendar) ) this.hideCalendar();
	},
	
	padZero: function(num) {
		return (num	< 10) ? '0' + num : num;
	},

	constructDate: function(d, m, y) {
		sTmp = this.options.format;
		sTmp = sTmp.replace('dd', '<e>');
		sTmp = sTmp.replace('d', '<d>');
		sTmp = sTmp.replace('<e>', this.padZero(d));
		sTmp = sTmp.replace('<d>', d);
		sTmp = sTmp.replace('mmmm', '<p>');
		sTmp = sTmp.replace('mmm', '<o>');
		sTmp = sTmp.replace('mm', '<n>');
		sTmp = sTmp.replace('m', '<m>');
		sTmp = sTmp.replace('<m>', m+1);
		sTmp = sTmp.replace('<n>', this.padZero(m+1));
		sTmp = sTmp.replace('<o>', this.monthName[this.options.language][m]);
		sTmp = sTmp.replace('<p>', this.monthName2[this.options.language][m]);
		sTmp = sTmp.replace('yyyy', y);
		return sTmp.replace('yy', this.padZero(y%100));
	},

	closeCalendar: function() {
		this.element.value = this.constructDate(this.dateSelected.date, this.dateSelected.month, this.dateSelected.year);
		this.hideCalendar();
		if (this.options.onDateClick) {
			this.options.onDateClick.call();
		}
	},

	/*** Month Pulldown	***/
	incMonth: function(event) {
		Event.stop(event);

		this.dateSelected.month++;
		if (this.dateSelected.month > 11) {
			this.dateSelected.month = 0;
			this.dateSelected.year++;
		}
		this.constructCalendar();
	},

	decMonth: function(event) {
		Event.stop(event);
		
		this.dateSelected.month--;
		if (this.dateSelected.month < 0) {
			this.dateSelected.month = 11;
			this.dateSelected.year--;
		}
		this.constructCalendar();
	},

	/*** Year Pulldown ***/
	incYear: function(event) {
		Event.stop(event);
		
		this.nStartingYear = this.nStartingYear + 4;
		var year = this.nStartingYear;

		this.selectmonthyear.select('.calendarYear').each(function(element) {
			element.removeClassName('selected');
			element.down().update(year);
			if (year == this.dateSelected.year) element.addClassName('selected');
			year++;
		}.bind(this));
	},

	decYear: function(event) {
		Event.stop(event);

		this.nStartingYear = this.nStartingYear - 4;
		var year = this.nStartingYear;

		this.selectmonthyear.select('.calendarYear').each(function(element) {
			element.removeClassName('selected');
			element.down().update(year);
			if (year == this.dateSelected.year) element.addClassName('selected');
			year++;
		}.bind(this));
	},

	constructYear: function() {
		var y = 0;
		var tbody = new Element('tbody');
		this.nStartingYear = this.dateSelected.year - 2;
		this.selectmonthyear.update('');
		
		for (i=0; i < 6; i++) {
			var row = new Element('tr');
			
			for (j=0; j < 2; j++) {
				var month = i + (j * 6);
				var cell = new Element('td');
				cell.update('<a href="#">' + this.monthName[this.options.language][month] + '</a>');
				if (month > 5) cell.addClassName('separator');
				if (month == this.dateSelected.month) cell.addClassName('selected');
				
				cell.observe('click', function(event, selectedMonth) {
					this.dateSelected.month = selectedMonth;
					this.constructCalendar();
					this.popDownYear();

					Event.stop(event);
				}.bindAsEventListener(this, month));
				
				row.appendChild(cell);
			}

			var cell = new Element('td');
			if (i == 0) {
				cell.update('<a id="prevyear" href="#"></a>');
				cell.observe('click', this.decYear.bindAsEventListener(this));
			} else if (i == 5) {
				cell.update('<a id="nextyear" href="#"></a>');
				cell.observe('click', this.incYear.bindAsEventListener(this));
			} else {
				var year = this.nStartingYear + y;
				
				cell.update('<a href="#">' + year + '</a>');
				cell.addClassName('calendarYear');
				if (year == this.dateSelected.year) cell.addClassName('selected');
				cell.observe('click', function(event) {
					selectedYear = parseInt(event.element().innerHTML);
					this.dateSelected.year = selectedYear;
					this.constructCalendar();
					this.popDownYear();

					Event.stop(event);
				}.bindAsEventListener(this));

				y++;
			}
			row.appendChild(cell);

			tbody.appendChild(row);
		}
		
		this.selectmonthyear.update(new Element('table').insert(tbody));
	},

	popDownYear: function() {
		this.selectmonthyear.hide();
	},

	popUpYear: function() {
		this.constructYear();
		this.selectmonthyear.show();
	},

	/*** calendar ***/
	constructCalendar: function() {
		sHTML = '<table><thead><tr>';
		for (i = 0; i < 7; i++) {
			sHTML += '<th>' + this.dayName[this.options.language][(i + this.options.startAt) % 7] + '</th>';
		}
		sHTML += '</tr></thead><tbody></tbody></table>';
		$('content').innerHTML = sHTML;

		var startDate = new Date(this.dateSelected.year, this.dateSelected.month, 1);
		dayPointer = startDate.getDay() - this.options.startAt;
		if (dayPointer < 0) dayPointer = 6;
		startDate.setDate(1 - dayPointer);

		var tbody = $('content').down('tbody'), row = new Element('tr');
		for	(i = 0; i < 43; i++ ) {
			var datePointer = {
				date: startDate.getDate(),
				month: startDate.getMonth(),
				year: startDate.getFullYear()
			};
			var cell = new Element('td');
			
			if (i > 0 && i % 7 == 0) {
				tbody.appendChild(row);
				row = new Element('tr');
			}

			if (this.odateSelected.date == datePointer.date && this.odateSelected.month == datePointer.month && this.odateSelected.year == datePointer.year) cell.addClassName('selected');
			if (this.today.date == datePointer.date && this.today.month == datePointer.month && this.today.year == datePointer.year) cell.addClassName('today');
			if (datePointer.month != this.dateSelected.month) cell.addClassName('other');
			if(startDate.getDay() == 0)
				cell.addClassName('sunday');
			else if(startDate.getDay() == 6)
				cell.addClassName('saturday');;

			cell.observe('click', function(event, selectedDay) {
				this.dateSelected.date = selectedDay.date;
				this.dateSelected.month = selectedDay.month;
				this.dateSelected.year = selectedDay.year;
				this.closeCalendar();

				Event.stop(event);
			}.bindAsEventListener(this, datePointer));
			
			cell.update('<a href="#">' + startDate.getDate() + '</a>');
			row.appendChild(cell);
			
			startDate.setDate(datePointer.date + 1);
		}

		$('spanmonthyear').innerHTML = this.monthName[this.options.language][this.dateSelected.month] + ' ' + this.dateSelected.year;
	},

	popUpCalendar: function() {
		var dateFormat = this.options.format;
		var formatChar = ' ';
		var aFormat = dateFormat.split(formatChar);
		var tokensChanged = 0;

		if (aFormat.length < 3) {
			formatChar = '/';
			aFormat = dateFormat.split(formatChar);
			if (aFormat.length < 3) {
				formatChar = '.';
				aFormat = dateFormat.split(formatChar);
				if (aFormat.length < 3) {
					formatChar = '-';
					aFormat = dateFormat.split(formatChar);
					if (aFormat.length < 3) {
						formatChar = '';					// invalid date format

					}
				}
			}
		}

		if (formatChar != "") {
			aData =	this.element.value.split(formatChar);	// use user's date
			for (i=0; i < 3; i++) {
				if ((aFormat[i] == "d") || (aFormat[i] == "dd")) {
					this.dateSelected.date = parseInt(aData[i], 10);
					tokensChanged++;
				} else if ((aFormat[i] == "m") || (aFormat[i] == "mm")) {
					this.dateSelected.month = parseInt(aData[i], 10) - 1;
					tokensChanged++;
				} else if (aFormat[i] == "yyyy") {
					this.dateSelected.year = parseInt(aData[i], 10);
					tokensChanged++;
				} else if (aFormat[i] == "mmm") {
					for (j=0; j<12; j++) {
						if (aData[i] == this.monthName[this.options.language][j]) {
							this.dateSelected.month = j;
							tokensChanged++;
						}
					}
				} else if (aFormat[i] == "mmmm") {
					for (j=0; j<12; j++) {
						if (aData[i] == this.monthName2[this.options.language][j]) {
							this.dateSelected.month = j;
							tokensChanged++;
						}
					}
				}
			}
		}

		if ((tokensChanged != 3) || isNaN(this.dateSelected.date) || isNaN(this.dateSelected.month) || isNaN(this.dateSelected.year)) {
			this.dateSelected  = Object.clone(this.today);
		}

		this.odateSelected  = Object.clone(this.dateSelected);

	    this.constructCalendar();
	    
	    var above = false;
		var w_pos = document.viewport.getScrollOffsets();
		var w_dim = document.viewport.getDimensions();
		var c_dim = this.calendar.getDimensions();
		var e_pos = this.element.cumulativeOffset();
		var e_dim = this.element.getDimensions();

	    if ((c_dim.height > (w_pos[1] + w_dim.height)) && (c_dim.height > w_pos[1])) above = true;
		var top_px = (above ? (e_pos[1] - c_dim.height) : (e_pos[1] + e_dim.height)) + 'px';
		var left_px = e_pos[0] + 'px';
		
		this.calendar.setStyle({left: left_px, top: top_px});
		this.calendar.show();
	},
	
	setStrings: function() {
		this.gotoString = {
			en : 'Go To Current Month',
			es : 'Ir al Mes Actual',
			de : 'Gehe zu aktuellem Monat',
			it : 'Vai al mese corrente'
		};
		this.todayString = {
			en : 'Today is',
			es : 'Hoy es',
			de : 'Heute ist',
			it : 'Oggi \u00E8'
		};
		this.monthName = {
			en : new Array('January','February','March','April','May','June','July','August','September','October','November','December'),
			es : new Array('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'),
			de : new Array('Januar','Februar','M\u00E4rz','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'),
			it : new Array('Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre')
		};
		this.monthName2 = {
			en : new Array('Jan','Feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'),
			es : new Array('Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'),
			de : new Array('Jan','Feb','Mrz','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'),
			it : new Array('Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic')
		};
		this.dayName = {
			en : new Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat'),
			es : new Array('Dom','Lun','Mar','Mie','Jue','Vie','Sab'),
			de : new Array('So','Mo','Di','Mi','Do','Fr','Sa'),
			it : new Array('Dom','Lun','Mar','Mer','Gio','Ven','Sab')
		};
	}
};
