/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.html.PHProjektDatePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.PHProjektDatePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
dojo.require("dojo.date");

/*
	Some assumptions:
	- I'm planning on always showing 42 days at a time, and we can scroll by week,
	not just by month or year
	- To get a sense of what month to highlight, I basically initialize on the 
	first Saturday of each month, since that will be either the first of two or 
	the second of three months being partially displayed, and then I work forwards 
	and backwards from that point.
	Currently, I assume that dates are stored in the RFC 3339 format,
	because I find it to be most human readable and easy to parse
	http://www.faqs.org/rfcs/rfc3339.html: 		2005-06-30T08:05:00-07:00
*/

dojo.widget.defineWidget(
	"dojo.widget.html.PHProjektDatePicker",
	dojo.widget.HtmlWidget,
	{
		classConstructor: function() {
			// mixin dojo.widget.DatePicker non-demoninational code
			dojo.widget.PHProjektDatePicker.call(this);
			// today's date, JS Date object
			this.today = "";
			// selected date, JS Date object
			this.date = "";
			// rfc 3339 date
			this.storedDate = "";
			// date currently selected in the UI, stored in year, month, date in the format that will be actually displayed
			this.currentDate = {};
			// stored in year, month, date in the format that will be actually displayed
			this.firstSaturday = {};
            
            this.months = '';
		},
		classNames: {
			previous: "previousMonth",
			current: "currentMonth",
			next: "nextMonth",
			currentDate: "currentDate",
			selectedDate: "selectedItem"
		},
		templatePath:  dojo.uri.dojoUri("src/widget/templates/PHProjektHtmlDatePicker.html"),
		templateCssPath:  dojo.uri.dojoUri("src/widget/templates/PHProjektHtmlDatePicker.css"),

		fillInTemplate: function(){
			dojo.widget.PHProjektDatePicker.call(this);
			this.initData();
			this.initUI();
		},
		initData: function() {
			this.today = new Date();
			if(this.storedDate && (this.storedDate.split("-").length > 2)) {
				this.date = dojo.widget.PHProjektDatePicker.util.fromRfcDate(this.storedDate);
			} else {
				this.date = this.today;
			}
			// calendar math is simplified if time is set to 0
			this.today.setHours(0);
			this.date.setHours(0);
			var month = this.date.getMonth();
			var tempSaturday = dojo.widget.PHProjektDatePicker.util.initFirstSaturday(this.date.getMonth().toString(), this.date.getFullYear());
			this.firstSaturday.year = tempSaturday.year;
			this.firstSaturday.month = tempSaturday.month;
			this.firstSaturday.date = tempSaturday.date;

            var count = 0;
            for (var i = dojo.date.firstSaturday - 7; count < 7; i++) {
                var pos = i - 1;
                if( pos > 6) { pos = i-8;}
                this.setDatesLabel(count,pos);
                count++;
            }
		},
		
		setDatesLabel: function(indexTd, indexTxt) {
	        var datesNodes = this.datesContainerNode.getElementsByTagName("td");
			var currentDateNode = datesNodes.item(indexTd);
			currentDateNode.innerHTML = dojo.date.days[indexTxt];
		},

		setDate: function(rfcDate) {
			this.storedDate = rfcDate;
		},
		
		initUI: function() {
			this.selectedIsUsed = false;
			this.currentIsUsed = false;
			var currentClassName = "";
			var previousDate = new Date();
			var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
			var currentCalendarNode;
			// set hours of date such that there is no chance of rounding error due to 
			// time change in local time zones
			previousDate.setHours(8);
			var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
			
			if(this.firstSaturday.date < 7) {
				// this means there are days to show from the previous month
				var dayInWeek = 6;
				for (var i=this.firstSaturday.date; i>0; i--) {
					currentCalendarNode = calendarNodes.item(dayInWeek);
					currentCalendarNode.innerHTML = nextDate.getDate();
					dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
					dayInWeek--;
					previousDate = nextDate;
					nextDate = this.incrementDate(nextDate, false);
				}
				for(var i=dayInWeek; i>-1; i--) {
					currentCalendarNode = calendarNodes.item(i);
					currentCalendarNode.innerHTML = nextDate.getDate();
					dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
					previousDate = nextDate;
					nextDate = this.incrementDate(nextDate, false);				
				}
			} else {
				nextDate.setDate(this.firstSaturday.date-6);
				for(var i=0; i<7; i++) {
					currentCalendarNode = calendarNodes.item(i);
					currentCalendarNode.innerHTML = nextDate.getDate();
					dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
					previousDate = nextDate;
					nextDate = this.incrementDate(nextDate, true);				
				}
			}
			previousDate.setDate(this.firstSaturday.date);
			previousDate.setMonth(this.firstSaturday.month);
			previousDate.setFullYear(this.firstSaturday.year);
			nextDate = this.incrementDate(previousDate, true);
			var count = 7;
			currentCalendarNode = calendarNodes.item(count);
			while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
				currentCalendarNode.innerHTML = nextDate.getDate();
				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
				currentCalendarNode = calendarNodes.item(++count);
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, true);
			}
			
			while(count < 42) {
				currentCalendarNode.innerHTML = nextDate.getDate();
				dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
				currentCalendarNode = calendarNodes.item(++count);
				previousDate = nextDate;
				nextDate = this.incrementDate(nextDate, true);
			}
			this.setMonthLabel(this.firstSaturday.month);
			this.setYearLabels(this.firstSaturday.year);
		},
		
		incrementDate: function(date, bool) {
			// bool: true to increase, false to decrease
			var time = date.getTime();
			var increment = 1000 * 60 * 60 * 24;
			time = (bool) ? (time + increment) : (time - increment);
			var returnDate = new Date();
			returnDate.setTime(time);
			return returnDate;
		},
		
		incrementWeek: function(evt) {
			var date = this.firstSaturday.date;
			var month = this.firstSaturday.month;
			var year = this.firstSaturday.year;
			switch(evt.target) {
				case this.increaseWeekNode.getElementsByTagName("img").item(0): 
				case this.increaseWeekNode:
					date = date + 7;
					if (date>this._daysIn(month,year)) {
						date = date - this._daysIn(month,year);
						if (month < 11) {
							month++;	
						} else {
							month=0;
							year++;
						}
					}
					break;
				case this.decreaseWeekNode.getElementsByTagName("img").item(0):
				case this.decreaseWeekNode:
					if (date > 7) {
						date = date - 7;
					} else {
						var diff = 7 - date;
						if (month > 0) {
							month--;
							date = this._daysIn(month,year) - diff;
						}else {
							year--;
							month=11;
							date = 31 - diff;
						}
					}
					break;
	
			}
	
			this.firstSaturday.date=date;
			this.firstSaturday.month=month;
			this.firstSaturday.year=year;
			this.initUI();
		},
	
		incrementMonth: function(evt) {
			var month = this.firstSaturday.month;
			var year = this.firstSaturday.year;
			switch(evt.currentTarget) {
				case this.increaseMonthNode:
					if(month < 11) {
						month++;
					} else {
						month = 0;
						year++;
						
						this.setYearLabels(year);
					}
					break;
				case this.decreaseMonthNode:
					if(month > 0) {
						month--;
					} else {
						month = 11;
						year--;
						this.setYearLabels(year);
					}
					break;
				case this.increaseMonthNode.getElementsByTagName("img").item(0):
					if(month < 11) {
						month++;
					} else {
						month = 0;
						year++;
						this.setYearLabels(year);
					}
					break;
				case this.decreaseMonthNode.getElementsByTagName("img").item(0):
					if(month > 0) {
						month--;
					} else {
						month = 11;
						year--;
						this.setYearLabels(year);
					}
					break;
			}
			var tempSaturday = dojo.widget.PHProjektDatePicker.util.initFirstSaturday(month.toString(), year);
			this.firstSaturday.year = tempSaturday.year;
			this.firstSaturday.month = tempSaturday.month;
			this.firstSaturday.date = tempSaturday.date;
			this.initUI();
		},
	
		incrementYear: function(evt) {
			var year = this.firstSaturday.year;
			switch(evt.target) {
				case this.nextYearLabelNode:
					year++;
					break;
				case this.previousYearLabelNode:
					year--;
					break;
			}
			var tempSaturday = dojo.widget.PHProjektDatePicker.util.initFirstSaturday(this.firstSaturday.month.toString(), year);
			this.firstSaturday.year = tempSaturday.year;
			this.firstSaturday.month = tempSaturday.month;
			this.firstSaturday.date = tempSaturday.date;
			this.initUI();
		},
	
		_daysIn: function(month,year) {
			var daysIn = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 
			
			if (month==1) {
				return (year%400 == 0) ? 29: (year%100 == 0) ? 28: (year%4 == 0) ? 29: 28;
			} else {
				return daysIn[month];
			}
		},
	
		onIncrementDate: function(evt) {
			dojo.unimplemented('dojo.widget.html.PHProjektDatePicker.onIncrementDate');
		},
	
		onIncrementWeek: function(evt) {
			evt.stopPropagation();
			this.incrementWeek(evt);
		},
	
		onIncrementMonth: function(evt) {
			evt.stopPropagation();
			this.incrementMonth(evt);
		},
		
		onIncrementYear: function(evt) {
			evt.stopPropagation();
			this.incrementYear(evt);
		},
	
		setMonthLabel: function(monthIndex) {
			this.monthLabelNode.innerHTML = dojo.date.months[monthIndex];
		},
		
		setYearLabels: function(year) {
			this.previousYearLabelNode.innerHTML = year - 1;
			this.currentYearLabelNode.innerHTML = year;
			this.nextYearLabelNode.innerHTML = year + 1;
		},
		
		getDateClassName: function(date, monthState) {
			var currentClassName = this.classNames[monthState];
			if ((!this.selectedIsUsed) && (date.getDate() == this.date.getDate()) && (date.getMonth() == this.date.getMonth()) && (date.getFullYear() == this.date.getFullYear())) {
				currentClassName = this.classNames.selectedDate + " " + currentClassName;
				this.selectedIsUsed = 1;
			}
			if((!this.currentIsUsed) && (date.getDate() == this.today.getDate()) && (date.getMonth() == this.today.getMonth()) && (date.getFullYear() == this.today.getFullYear())) {
				currentClassName = currentClassName + " "  + this.classNames.currentDate;
				this.currentIsUsed = 1;
			}
			return currentClassName;
		},
	
		onClick: function(evt) {
			dojo.event.browser.stopEvent(evt)
		},
		
		onSetDate: function(evt) {
			dojo.event.browser.stopEvent(evt);
			this.selectedIsUsed = 0;
			this.todayIsUsed = 0;
			var month = this.firstSaturday.month;
			var year = this.firstSaturday.year;
			if (dojo.html.hasClass(evt.target, this.classNames["next"])) {
				month = ++month % 12;
				// if month is now == 0, add a year
				year = (month==0) ? ++year : year;
			} else if (dojo.html.hasClass(evt.target, this.classNames["previous"])) {
				month = --month % 12;
				// if month is now == 0, add a year
				year = (month==11) ? --year : year;
			}
			this.date = new Date(year, month, evt.target.innerHTML);
			this.setDate(dojo.widget.PHProjektDatePicker.util.toRfcDate(this.date));
			this.initUI();
		}
	}
);
