DateSelectControl = Class.create();
DateSelectControl.CLOSED_VERBOSE = "Unfortunately we are closed on this date - please choose another date.";
DateSelectControl.CLOSED = "Closed"
DateSelectControl.FULLY_BOOKED_VERBOSE = "Unfortunately we are fully booked - please choose another date.";
DateSelectControl.FULLY_BOOKED = "Fully Booked";
DateSelectControl.NO_BOOKINGS_VERBOSE = "Unfortunately that date is unavailable - please choose another date.";
DateSelectControl.NO_BOOKINGS = "Date Unavailable";
DateSelectControl.STATUS_OK = "If you are making a booking for this evening, the latest you can book is 7pm Mon &amp; Tue, and 6pm Wed, Thur &amp; Fri.";
DateSelectControl.prototype = {

	initialize: function(element, date, options) {
		
		this.dateControl = new Date();
		this.dateControl.setFromTimestamp(date);	
		this.rangeStartDate = new Date();	
		this.rangeEndDate = new Date();	
		this.bookedDays = new Array();
		this.closedDates = new Array();
		this.rangeStartDate.setFromTimestamp(options.rangeStartDate);
		
		this.englishMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
		this.dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

		this.options = {
    		rangeStartDate: new Date(),
     		rangeEndDate: new Date(),
	      	seatingGroupId: "",
	      	currentDate: new Date()
    	};
    	
		Object.extend(this.options, options || { });

		if (this.rangeStartDate <= new Date()) {
			this.rangeStartDate.setFromTimestamp(new Date());
			this.rangeStartDate.setMilliseconds(0);
			this.rangeStartDate.setSeconds(0);
			this.rangeStartDate.setMinutes(0);
			this.rangeStartDate.setHours(0);
		}

		this.rangeEndDate.setFromTimestamp(options.rangeEndDate);
		this.rangeEndDate.setMilliseconds(0);
		this.rangeEndDate.setSeconds(0);
		this.rangeEndDate.setMinutes(0);
		this.rangeEndDate.setHours(0);		

		if (this.dateControl.getTime() <= this.rangeStartDate.getTime()) {
			this.dateControl.setFromTimestamp(this.rangeStartDate);
		}	else if (this.dateControl.getTime() >= this.rangeEndDate.getTime()){
			this.dateControl.setFromTimestamp(this.rangeEndDate);
		}

		
		this.dateControl.setSeconds(0);
		this.dateControl.setMinutes(0);
		this.dateControl.setHours(0);	
		this.dateControl.setMilliseconds(0);

		this.element = $(element);
		Element.extend(this.element);
		
		this.statusElement = document.createElement("div");
		Element.extend(this.statusElement);
		this.element.appendChild(this.statusElement);		
		
		this.daySelect = document.createElement("div");
		Element.extend(this.daySelect);
		this.element.appendChild(this.daySelect);
		
		this.dateSelect = document.createElement("div");
		Element.extend(this.dateSelect);
		this.element.appendChild(this.dateSelect);
		
		this.monthSelect = document.createElement("div");
		Element.extend(this.monthSelect);
		this.element.appendChild(this.monthSelect);
		
		this.yearSelect = document.createElement("div");
		Element.extend(this.yearSelect);
		this.element.appendChild(this.yearSelect);
		
		this.populateCalendar();
	},
	
	getWeekStartingTime: function() {
		var dow = this.dateControl.getDay();
		var weekStartingTime = new Date();
		weekStartingTime.setFromTimestamp(this.dateControl.getTime() - dow * 86400000);

		return weekStartingTime;
	},

	requestDayElement: function() {
		weekStartingTime = new Date(this.getWeekStartingTime());

		var output = new Ajax.Request(SeatingAreaControl.serviceURL, {
			parameters: {
				Action: "WeekAvailability",
				seatingGroupId: this.options.seatingGroupId,
				BookingDate: weekStartingTime.getTime()
			},
			onSuccess: (function(response) {
				response = response.responseText.evalJSON();
				if (response.success) {
					this.bookedDays = response.data.split(",");				
					for (var i = 0; i <= 6; i++) {
						var day = $("day-" + i);
						if (this.bookedDays[i] == "true") {
							day.addClassName("booked");
							day.title = DateSelectControl.FULLY_BOOKED;
							statusNote = $("status-note");
							var date = new Date(day.date);
							if (date.getDate() == this.dateControl.getDate()) {
								statusNote.innerHTML = DateSelectControl.FULLY_BOOKED_VERBOSE;							
							}
						} else {
							day.removeClassName("booked");
						}
					}
				}
			}).bind(this)
		});	
	},
	
	requestClosedDates: function() {	
		weekStartingTime = new Date(this.getWeekStartingTime());
	
		var myTime = new Date();
		myTime.setFromTimestamp(this.dateControl.getTime());
		myTime.setDate(1);
		
		new Ajax.Request(SeatingAreaControl.serviceURL, {
			method: "get",
			parameters: {
				Action: "ClosedDates",
				seatingGroupId: this.options.seatingGroupId,
				BookingDate: myTime.getFullYear() + "-" + (myTime.getMonth() + 1) + "-" + myTime.getDate()
			},
			onSuccess: (function(response) {
				response = response.responseText.evalJSON();
				if (response.success) {
					this.closedDates = response.data.split(",");
					for (var i = 0; i <= 31; i++) {
						var date = $("date-" + i);
						if (date) {
							if (this.closedDates[i] == "true") {
								date.addClassName("closed");	
								date.onclick = null;		
								date.title = DateSelectControl.CLOSED;
							} else {
								date.removeClassName("closed");
							}					
						}
					}
					for (var i = 0; i <= 6; i++) {
						var day = $("day-" + i);
						if (day) {
							if (this.closedDates[(i + (weekStartingTime.getDate() -1))] == "true") {
								day.addClassName("closed");	
								day.title = DateSelectControl.CLOSED;		
								day.onclick = null;			
							} else {
								day.removeClassName("closed");
							}					
						}
					}										
				}
			}).bind(this)
		});
	},		

	changeDate: function(time) {
		var time = new Date(time);
	
		time.setMilliseconds(0);
		time.setSeconds(0);
		time.setMinutes(0);
		time.setHours(0);			
	
		this.beforeDateChange(time);
		this.dateControl.setTime(time);
		this.populateCalendar();
	},
	
	setBooked: function(bookedDates) {
		for (var i = 0; i <= 6; i++) {
			this.bookedDays[i] = bookedDates[i];
		}
	},
	
	
	isAllowedDate: function(myTime, denomination, startOfMonth, endOfMonth) {
		if ((denomination == "date" || denomination == "week") && (myTime.getDay() == 0 || myTime.getDay() == 6)) {
			return false;		
		}
		switch (denomination) {
			case "date":				
				if ((myTime.getTime() >= this.rangeStartDate.getTime()) && (myTime.getTime() <= this.rangeEndDate.getTime())) {
					return myTime;
				} else {
					return false;
				}
				break;
			case "month":
				if ((myTime.getTime() >= this.rangeStartDate.getTime()) && (myTime.getTime() <= this.rangeEndDate.getTime())) {
					return myTime;
				} else {
					if ((myTime.getMonth() == this.rangeStartDate.getMonth()) && (myTime.getYear() == this.rangeStartDate.getYear())) {
						if (startOfMonth < this.rangeStartDate) {
							return this.rangeStartDate;
						} else {
							return myTime;
						}
						return startOfMonth;
					} else if ((myTime.getMonth() == this.rangeEndDate.getMonth()) && (myTime.getYear() == this.rangeEndDate.getYear())) {
						if (endOfMonth > this.rangeStartDate) {
							return this.rangeEndDate;
						} else {
							return myTime;
						}
					}
					return false;
				}
				break;
			case "week":
				if ((myTime.getTime() >= this.rangeStartDate.getTime()) && (myTime.getTime() <= this.rangeEndDate.getTime())) {
					return myTime;
				} else {
					return false;
				}
				break;
		}
	},	

	populateCalendar: function() {
		this.populateStatus();
		this.populateDayElement();
		this.populateDateElement();
		this.populateMonthElement();
		this.populateYearElement();		
		this.requestDayElement();
		this.requestClosedDates();				
	},
	
	populateStatus: function() {
		this.statusElement.id = "status-bar";
		
		var description = ""; 
		
		if (this.dateControl.getDay() >= 1 && this.dateControl.getDay() <= 2) {
			description = "The latest you can book a booth for this evening is 7pm.";
		} else {
			description = "The latest you can book a booth for this evening is 6pm.";
		}
		
		this.statusElement.innerHTML = 
			"<p>Current date selected is " + this.dayNames[this.dateControl.getDay()] + " " + this.dateControl.getDate() + " " + this.englishMonths[this.dateControl.getMonth()] + " " + this.dateControl.getFullYear() + ". " +
			"<span id=\"status-note\">" + description + "</span></p>";
	},
		
	populateDayElement: function() {
		this.daySelect.innerHTML = "";

		this.daySelect.id = "day-container";
		this.dateControl.getTime();
		var dow = this.dateControl.getDay();
		
		var weekStartingTime = this.dateControl.getDate() - dow;
		var myTime = this.dateControl.getTime();
		var myDate = new Date(myTime);
		weekStartingTime = myDate.setDate(weekStartingTime);

		var startOfWeekDay = (new Date(weekStartingTime)).getDate();

		var dayEarlier = document.createElement("div");
		Element.extend(dayEarlier);
		this.daySelect.appendChild(dayEarlier);
		dayEarlier.innerHTML = "<span>Earlier</span>";
		dayEarlier.className = "day-change";
		dayEarlier.id = "earlier";
		var	weekEarlier = new Date();
		weekEarlier.setFromTimestamp(this.dateControl.getTime() - 604800000);

		if (weekEarlier <= this.rangeStartDate) {
			weekEarlier.setFromTimestamp(this.rangeStartDate);
		}
		
		if (this.dateControl.getTime() == this.rangeStartDate.getTime()) {
			dayEarlier.addClassName("date-change-unavailable");
		}
		
		if (this.dateControl.getTime() > this.rangeStartDate.getTime()) {
			dayEarlier.onclick = (function(time) {
				this.changeDate(time.getTime());
	 		}).bind(this, weekEarlier);		
		} else if (this.dateControl.getTime() == this.rangeStartDate.getTime()) {
			dayEarlier.addClassName("date-change-unavailable");
		}

		for (var i = 0; i <= 6; i++) {
			var day = document.createElement("div");
			day.id = "day-" + i;

			Element.extend(day);
			this.daySelect.appendChild(day);	

			day.innerHTML = "<span>" + this.dayNames[i] + "</span>" + "<strong>" + (new Date(weekStartingTime + i * 86400000)).getDate() + "</strong>";
			day.className = "day";

			if (this.dateControl.getDay() == i) {
				day.addClassName("current");
			}

			var myTime = new Date();
			myTime.setFromTimestamp(weekStartingTime + i * 86400000);

			var allowedDate = this.isAllowedDate(myTime, "week");

			if (allowedDate != false) {
				day.onclick = (function(time) {
					this.changeDate(time.getTime());
				}).bind(this, allowedDate);				
			} else {
				day.addClassName("unavailable");
				day.title = DateSelectControl.NO_BOOKINGS;
			}
		}
		
		var dayLater = document.createElement("div");
		this.daySelect.appendChild(dayLater);	
		dayLater.innerHTML = "<span>Later</span>";
		dayLater.className = "day-change";
		dayLater.id = "later";
		var	weekLater = new Date();
		weekLater.setFromTimestamp(this.dateControl.getTime() + 604800000);	
		if (weekLater >= this.rangeEndDate) {
			weekLater.setFromTimestamp(this.rangeEndDate);
			dayLater.addClassName("time-change-unavailable");
		}
		
		if (this.dateControl.getTime() < this.rangeEndDate.getTime()) {
			dayLater.onclick = (function(time) {
				this.changeDate(time.getTime());
	 		}).bind(this, weekLater);		
		} else if (this.dateControl.getTime() == this.rangeEndDate.getTime()) {
			dayEarlier.addClassName("date-change-unavailable");
		}
	},
		
	populateDateElement: function() {
		this.dateSelect.innerHTML = "";
		this.dateSelect.id = "date-container";
		
		var februaryControl = new Date(this.dateControl);
		
		februaryControl.setMonth(2, 1);
		februaryControl.setFromTimestamp(februaryControl.getTime() - 86400000);
	
		var monthLengths = [31, februaryControl.getDate(), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
		for (var i = 1; i <= monthLengths[this.dateControl.getMonth()]; i++) {
			var date = document.createElement("div");
			Element.extend(date);
			date.id = "date-" + (i - 1);
			this.dateSelect.appendChild(date);
			
			var myTime = new Date();
			myTime.setFromTimestamp(this.dateControl);
			myTime.setDate(i);		
			
			date.innerHTML = "<span>" + i + "</span>";
			date.className = "date";
			
			if (this.dateControl.getDate() == i) {
				date.addClassName("current");
			}

			var allowedDate = this.isAllowedDate(myTime, "date");

			if (allowedDate != false) {
				date.onclick = (function(time) {
					this.changeDate(time.getTime());
				}).bind(this, allowedDate);						
			} else {
				date.addClassName("unavailable");
			}
		}	
	},
	
	populateMonthElement: function() {
		this.monthSelect.innerHTML = "";
		this.monthSelect.id = "month-container";

		for (var i = 0; i <= 11; i++) {
			var month = document.createElement("div");
			Element.extend(month);
			var myTime = new Date(this.dateControl);
			myTime.setMonth(i, 1);
			myTime.setYear(this.dateControl.getFullYear());
			this.monthSelect.appendChild(month);
			month.innerHTML = "<span>" + this.englishMonths[i] + "</span>";
			month.className = "month";
			if (this.dateControl.getMonth() == i) {
				month.addClassName("current");
			}
			var rangeStartDateMonthStamp = this.rangeStartDate.getTime() - ((this.rangeStartDate.getDate() -1) * 86400000);
			var rangeStartDateMonth = new Date();
			rangeStartDateMonth.setFromTimestamp(rangeStartDateMonthStamp);
			
			var rangeEndDateMonthStamp = this.rangeEndDate.getTime() - ((this.rangeEndDate.getDate() - 1) * 86400000);
			var rangeEndDateMonth = new Date();
			rangeEndDateMonth.setFromTimestamp(rangeEndDateMonthStamp);
			
			var allowedDate = this.isAllowedDate(myTime, "month", rangeStartDateMonth, rangeEndDateMonth);

			if (allowedDate != false) {
				month.onclick = (function(time) {
					this.changeDate(time.getTime());
				}).bind(this, allowedDate);				
			} else {
				month.addClassName("unavailable");
			}			
		}
	},
	
	populateYearElement: function() {
		this.yearSelect.innerHTML = "";
		this.yearSelect.id = "year-container";

		//This years
		var year = document.createElement("div");
		Element.extend(year);
		this.yearSelect.appendChild(year);
		var myTime = new Date();
		myTime.setYear(this.rangeStartDate.getFullYear());
		
		year.innerHTML = "<span>" + myTime.getFullYear() + "</span>";
		year.className = "year";
		if (this.dateControl.getFullYear() == myTime.getFullYear()) {
			year.addClassName("current");
		}
		if ((this.rangeStartDate <= myTime) && (this.rangeEndDate >= myTime)) {
			year.onclick = (function(time) {
				this.changeDate(time.getTime());
  		}).bind(this, this.rangeStartDate);
  	} else {
	  	year.addClassName("unavailable");	  	
  	}		
		
		//Next years
		var year = document.createElement("div");
		Element.extend(year);
		this.yearSelect.appendChild(year);
		var myTime = new Date();
		myTime.setYear(this.rangeStartDate.getFullYear() + 1);
		myTime.setDate(1);
		myTime.setMonth(0);
		
		year.innerHTML = "<span>" + myTime.getFullYear() + "</span>";
		year.className = "year";
		if (this.dateControl.getFullYear() == myTime.getFullYear()) {
			year.addClassName("current");
		}
		if ((this.rangeStartDate <= myTime) && (this.rangeEndDate >= myTime)) {
			year.onclick = (function(time) {
				this.changeDate(time.getTime());
  		}).bind(this, myTime);
  	} else {
	  	year.addClassName("unavailable");
  	}		
	}	
}
