/*
	MooCal v0.2 - A simple and easy to use calendar control built upon mooTools
	by Chris Martin (http://www.redantdesign.com/) - MIT-style license.
	
	The draw function is modified from a date picker control written by David Kelly 
	* Copyright 2007 David Kelly for CJD Systems Limited
	* version 0.1 - 21st May 2007
	* url - http://ng100.cjdsystems.co.uk/moo/dates/DateTimePicker.htm

*/

var MooCal = new Class({
	initialize: function(elementID, options){
		this.setOptions({
			base: 1,
			x:0,
			y:0,
			calendarClass: "calendar",
			todayClass: "today",
			selectedClass: "selected",
			inactiveClass: "inactive",
			closeClass: "close",
			hdrDayClass: "hdrday",
			cancelchoice: true,
			defaultYear: new Date().getFullYear(),
			defaultMonth: new Date().getMonth(),
			defaultDay: new Date().getDate(),
			dayNames: ["S", "M", "T", "W", "T", "F", "S", "S"],
			monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
			minDate: new Date(),
			maxDate: null
		}, options);
		
		 
        this.options.maxDate = new Date();
         //add a day to the date
        this.options.maxDate.setDate(this.options.minDate.getDate() + 27);   	    		
		this.calendarID = null;
		this.visible = true;
		this.displayTimer = 0;
		this.minYear = this.options.minDate.getFullYear();
		this.maxYear = this.options.maxDate.getFullYear();
		this.elementID = elementID;
		this.yearElement = $(elementID + "-year");
		this.monthElement = $(elementID + "-month");
		this.dayElement = $(elementID + "-day");		
		this.chosenDate = new Date();
		
		if(this.yearElement){
			this.year = this.yearElement.getValue();
			if(this.yearElement.getTag() == "select"){
				var totalOptions = this.yearElement.length - 1;
				if(totalOptions > 0){
					var firstOptionValue = this.yearElement.options[0].value;
					var lastOptionValue = this.yearElement.options[totalOptions].value;
					
					if(firstOptionValue < lastOptionValue){
						this.minYear = firstOptionValue;
						this.maxYear = lastOptionValue;
					} else {
						this.minYear = lastOptionValue;
						this.maxYear = firstOptionValue;
					}
				}
			}
		} else {
			this.year = this.options.defaultYear;
		}
		
		this.chosenDate.setYear(this.year);
		
		if(this.monthElement){
			this.month = this.monthElement.getValue() - this.options.base;
		} else {
			this.month = this.options.defaultMonth;
		}
		
		this.chosenDate.setMonth(this.month);
		
		if(this.dayElement){
			this.day = this.dayElement.getValue();
		} else {
			this.day = this.options.defaultDay;
		}
		this.chosenDate.setDate(this.day);

		this.minDate = (this.options.minDate) ?
		    new Date(this.options.minDate).setHours(0, 0, 0, 0) : null;
		this.maxDate = (this.options.maxDate) ?
		  new Date(this.options.maxDate).setHours(23, 59, 59, 999) : null;
		this.chosenDate = this.withinBounds(this.chosenDate);
		this.currentDate = this.chosenDate;
		
		this.monthAndYear = null;

	},

	withinBounds: function (d) {
		if (this.minDate && d < this.minDate) {
			return new Date(this.minDate);
		}
		if (this.maxDate && d > this.maxDate) {
			return new Date(this.maxDate);
		}
		return new Date(d);
	},

	isAllowed: function (d) {
		return (this.minDate == null || d >= this.minDate) &&
			   (this.maxDate == null || d <= this.maxDate);
	},

	show: function(x, y) {
		if(this.visible && this.calendarID == null){
			this.calendarID = "calendar_" + Date.parse(new Date());
			this.draw($pick(x, this.options.x), $pick(y, this.options.y));
		} else {
			this.redraw();
			$(this.calendarID).setStyles({
				"display":"block",
				"left": 318,
				"top": 227
				//"left":$pick(x, this.options.x),
				//"top":$pick(y, this.options.y)
			});
		}
		
		this.visible = true;
	},
	
	hide: function() {
		if(this.visible){
			$(this.calendarID).setStyle("display","none");
			this.visible = false;
			clearTimeout(this.displayTimer);
		}
	},
	
	selectDate: function(e,d) {
		new Event(e).stop();
		
		if($type(d) != "number") 
			return;

		if (!this.isAllowed(new Date(this.currentDate).setDate(d))) {
			return;
		}
		
		this.currentDate.setDate(d);
		this.chosenDate = this.currentDate;
		
		if(this.yearElement)
			this.yearElement.setProperty("value", this.currentDate.getFullYear());
		if(this.monthElement)
			this.monthElement.setProperty("value", this.currentDate.getMonth() + this.options.base);
		if(this.dayElement)
			this.dayElement.setProperty("value", this.currentDate.getDate());
		if(!this.dayElement && !this.monthElement && !this.yearElement && $(this.elementID).getTag() == "input"){
			$(this.elementID).setProperty("value", this.options.monthNames[this.currentDate.getMonth()] + " " + this.currentDate.getDate() + ", " + this.currentDate.getFullYear());

		
		}
		
		this.hide();
		
		var callback=changeDate || function(){return true;}
		callback(this.currentDate);
	},
	
	setDates: function(){
		this.lastMonth = new Date(this.currentDate).setDate(0);
		this.nextMonth = new Date(this.currentDate).setMonth(this.currentDate.getMonth() + 1, 1);
		this.lastYear = new Date(this.currentDate).setFullYear(this.currentDate.getFullYear() - 1, this.currentDate.getMonth() + 1, 0);
		this.nextYear = new Date(this.currentDate).setFullYear(this.currentDate.getFullYear() + 1, this.currentDate.getMonth(), 1);
		this.today = new Date();
	},
		
	repaint: function(e,d) {
		
		new Event(e).stop();
		var dateToCheck = new Date(d);
		if(dateToCheck.getFullYear() < this.minYear || dateToCheck.getFullYear() > this.maxYear){
			return;
		}
		if (!this.isAllowed(dateToCheck)) { return; }
		this.currentDate = dateToCheck;
		this.setDates();
		this.redraw();
	},
	
	mouseOver: function() {
		clearTimeout(this.displayTimer);
	},
	
	mouseOut: function() {
		this.displayTimer = this.hide.delay(500, this); 
	},
	
	draw: function(x, y) {
		var tableContainer, table, thead, tbody, row, td;
		
		tableContainer = new Element("div",{ 
			"class": this.options.calendarClass,
			"id": this.calendarID,
			"events": {
				"mouseover": this.mouseOver.bind(this),
				"mouseout": this.mouseOut.bind(this)
			}
		})
		.setStyles({
			"position":"absolute",
			"left": 318,
			"top": 227
		});
		
		table = new Element("table", {
			"id": this.calendarID + "-table",
			"class": this.calendarID + "-table"
		});
		thead = new Element("thead").injectInside(table);
	
			row = new Element("tr").injectInside(thead);
				
				new Element("a", {
					"href":"#",
					"events":{
						"click": (function(e)
						        { 
						            this.repaint(e, this.lastMonth);
								    
							}).bindWithEvent(this)
					}
				}).setHTML("<img src=/pic/calArrowL.gif border=0>").injectInside(
					new Element("th", {
						  "class": this.options.calendarClass + "-monthswitch"
					}).injectInside(row)
				);
				
				this.monthAndYear = new Element("th", {
					  "colSpan": 5,  
					  "class" : this.options.calendarClass + "-monthandyear"
				}).appendText(this.options.monthNames[this.currentDate.getMonth()] + " " + this.currentDate.getFullYear()).injectInside(row);
				
				new Element("a", {
					"href":"#",
					"events":{
						"click": (function(e){ this.repaint(e, this.nextMonth);
							
						}).bindWithEvent(this)
					}
				}).setHTML("<img src=/pic/calArrowR.gif border=0>").injectInside(
					new Element("th", {
						  "class": this.options.calendarClass + "-monthswitch"
					}).injectInside(row)
				);
				
		
			row = new Element("tr").injectInside(thead);
				for (i = 0; i < 7; i++)	{ 
					new Element("th", {
						"class" : this.options.hdrDayClass
					}).appendText(this.options.dayNames[i]).injectInside(row);
				}
		
		tbody = new Element("tbody").injectInside(table);

		for(r=0;r<6;r++){
			row = new Element("tr").injectInside(tbody);
			for(c=0;c<7;c++){
				td = new Element("td").injectInside(row);
				new Element("a",{
					"href": ""
				}).setHTML("&nbsp;").injectInside(td);
			}
		}
		
		/** Add the close link */
     if (this.options.cancelchoice) {
	  	row = new Element("tr").injectInside(tbody);
		td = new Element("td", {
			      "class" : this.options.closeClass,
			      "colSpan": 7, 
				  "events": {
			      "click" : this.hide.bind(this)
			      }
			    }).appendText("Close").injectInside(row);
      }	
	/*****/
			
		table.injectInside(tableContainer);
		tableContainer.injectInside(document.body);
		
		this.redraw();
	},
	
	redraw: function() {
		this.setDates();
		this.monthAndYear.setText(this.options.monthNames[this.currentDate.getMonth()] + " " + this.currentDate.getFullYear());

		var controls = $ES("thead a", $(this.calendarID));
		var controlDates = [this.lastMonth, this.nextMonth];

		for (i = 0; i < controls.length; i++) {
			$(controls[i]).removeClass(this.options.inactiveClass);
			if (!this.isAllowed(controlDates[i]) ||
				new Date(controlDates[i]).getFullYear() < this.minYear ||
				new Date(controlDates[i]).getFullYear() > this.maxYear) {
				$(controls[i]).addClass(this.options.inactiveClass);
			}
		}	

		var dates = $ES("tbody a", $(this.calendarID));

		var firstDay = new Date(this.currentDate);
		firstDay.setDate(1);
		
		if (firstDay.getDay() > 0) {
			  firstDay.setDate(-firstDay.getDay() + 1);
		}

		var currentDay = new Date(firstDay);
		var today = new Date();
	
		for (i = 0; i < dates.length; i++) {	
			$(dates[i]).removeClass(this.options.todayClass);
			$(dates[i]).removeClass(this.options.selectedClass);
			$(dates[i]).removeClass(this.options.inactiveClass);

			var txt = "";
			if (currentDay.getMonth() == this.currentDate.getMonth()) {
				txt = currentDay.getDate();

				if (!this.isAllowed(currentDay)) {
					$(dates[i]).addClass(this.options.inactiveClass);
				}
			}

			$(dates[i]).removeEvents();
			$(dates[i]).addEvent("click", (function(e, day){
				this.selectDate(e, day);
				}).bindWithEvent(this, txt)
			);
			
			$(dates[i]).setHTML(txt);
			
			if (currentDay.getDate() == today.getDate() && currentDay.getMonth() == today.getMonth() && currentDay.getFullYear() == today.getFullYear()) {
				$(dates[i]).addClass(this.options.todayClass);
			}
			if (this.currentDate.getMonth() == this.chosenDate.getMonth() && currentDay.getDate() == this.chosenDate.getDate() && currentDay.getMonth() == this.chosenDate.getMonth() && currentDay.getFullYear() == this.chosenDate.getFullYear()) {
				$(dates[i]).addClass(this.options.selectedClass);
			}
			currentDay.setDate(currentDay.getDate() + 1);
		}
	}
});

MooCal.implement(new Options);
