/**
 * Copyright (c) 2006 Timothy Grant Vogelsang
 *
 * Author: Timothy Grant Vogelsang <tvogelsang@gmail.com>
 */

var days = new Array('S', 'M', 'T', 'W', 'T', 'F', 'S');
var dayNames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
var monthNames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');

/**
 * CalendarControl Class
 *
 */
var CalendarControl = Class.create();

CalendarControl.prototype = {
	/**
	 * Declare public values.
	 */
	variables: {
		dates: null,
		sessionDates: null,
		endDate: null,
		startDate: null,
		selectedDate: null
	},
	parameters: null,
	
	/**
	 * Gets the calendar name.
	 */
	getName: function() {
		return this.parameters.name;
	},
	
	/**
	 * Gets the calendar object.
	 */
	getObject: function() {
		return $(this.getName());
	},
	
	/**
	 * Gets the calendar year value.
	 */
	getCalendarYear: function() {
		return this.parameters.currentDate.getFullYear();
	},
	
	/**
	 * Gets the calendar month value.
	 */
	getCalendarMonth: function() {
		return this.parameters.currentDate.getMonth();
	},
	
	/**
	 * Gets the calendar month name value.
	 */
	getCalendarMonthName: function() {
		return monthNames[this.parameters.currentDate.getMonth()];
	},
	
	/**
	 * Gets the calendarControl object.
	 */
	getCalendarControl: function() {
		return $(this.parameters.clientId);
	},
	
	/**
	 * This public function handles the initialization routines.
	 */
	initialize: function(parameters) {
		this.parameters = parameters;
		this.variables.selectedDate = this.parameters.currentDate;
		
		this.render();
	},
	
	/**
	 * This public function handles the initialization of the calendar
	 * variables.
	 */
	initializeCalendar: function() {
		// Get start of the month
		this.variables.startDate =
			new Date(this.getCalendarYear(), this.getCalendarMonth(), 1);
		
		// Get end of the month
		this.variables.endDate =
			new Date(this.getCalendarYear(), this.getCalendarMonth() + 1, 0);
		
		this.variables.dates = new Array();
		
		var startDate = new Date(this.variables.startDate.getTime() -
			(this.variables.startDate.getDay() * 1000 * 60 * 60 * 24));
		var endDate = new Date(this.variables.endDate.getTime() +
			((6 - this.variables.endDate.getDay()) * 1000 * 60 * 60 * 24));
		
		var currentDate = new Date(startDate.getTime());
		
		// Scroll through the start and end date
		for (i = 0; currentDate.getTime() < endDate.getTime(); i++) {
			if (i > 0)
				currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate() + 1);
			
			this.variables.dates[i] = currentDate;
		}
		// alert(this.variables.dates);
	},
	
	/**
	 * This public function handles the initialization of the calendar
	 * contents.
	 */
	initializeContents: function() {
		/* if (CalendarView.GetCalendarSessions) {
			this.variables.sessionDates = eval(CalendarView.GetCalendarSessions(this.parameters.currentDate).value);
			
			// Scroll through each of the rows
			for (i = 0; this.variables.sessionDates.Rows.length > i; i++) {
				var row = this.variables.sessionDates.Rows[i];
				var date = (row.StartDate.getMonth() + 1) + '_' + row.StartDate.getDate() + '_' + row.StartDate.getFullYear();
				var span = $(date);
				
				this.renderContentDate(span, row);
			}
		} */
	},
	
	/**
	 * This public function handles the render of the control.
	 */
	render: function() {
		var calendarControl = this.getCalendarControl();
		
		calendarControl.className = 'calendarControl';
		calendarControl.style.width = this.parameters.width + 'px';
		
		this.initializeCalendar();
		
		this.renderContents(calendarControl);
		
		this.initializeContents();
	},
	
	/**
	 * This public function handles the render of the calendar title.
	 */
	renderTitle: function(calendarControl) {
		calendarControl.innerHTML =
			'<div id="calendarControlControlTitle" class="calendarControlTitle">' +
				'<table cellpadding="0" cellspacing="0" border="0" width="100%">' +
					'<tr>' +
						'<td><a href="#" onclick="' + this.getName() +  '.onPreviousClick(); return false;">&lt;&lt;</a></td>' +
						'<td align="center">' + this.getCalendarMonthName() + '&nbsp;' + this.getCalendarYear() + '</td>' +
						'<td align="right"><a href="#" onclick="' + this.getName() +  '.onNextClick(); return false;">&gt;&gt;</a></td>' +
					'</tr>' +
				'</table>' +
			'</div>';
	},
	
	/**
	 * This public function handles the render of the calendar contents.
	 */
	renderContents: function(calendarControl) {
		this.renderTitle(calendarControl);
		
		var content = '';
		
		content = '<div id="calendarControlControlContent" class="calendarControlContent">' +
				'<table cellpadding="0" cellspacing="0" border="0" width="100%" class="calendarControlDays">' +
					'<tr>';
		
		// Scroll through the days of the week
		for (i = 0; days.length > i; i++) {
			content += '<td>' + days[i] + '</td>';
		}
		
		content += '</tr>' +
				'</table>' +
				'<table cellpadding="0" cellspacing="0" border="0" width="100%" class="calendarControlDates">';
		
		content += this.renderContentDates();
		
		content += '</table>' +
			'</div>';
		
		calendarControl.innerHTML += content;
		
		var contentItems = '';
	},
	
	/**
	 * This public function handles the render of the calendar dates.
	 */
	renderContentDates: function() {
		var contentDates = '';
		
		// Scroll through the dates
		for (i = 0; this.variables.dates.length > i; i++) {
			var currentDate = this.variables.dates[i];
			
			// Start row
			if (currentDate.getDay() == 0) {
				if ((this.variables.dates.length - i) > 7)
					contentDates += '<tr class="calendarControlDateTop">';
				else
					contentDates += '<tr class="calendarControlDateBottom">';
			}
			
			contentDates += '<td id="_' + getDateId(currentDate) + '"';
			
			// Render weekend style
			if (currentDate.getMonth() != this.getCalendarMonth())
				contentDates += ' class="NotAvailable"';
			
			contentDates += ' onClick="' + this.getName() + '.onDateClick(' + currentDate.getTime() + ')">' +
								'<table cellpadding="0" cellspacing="0" border="0" width="100%" class="calendarControlDetails">' +
									'<tr>' +
										'<td valign="top">' +
											currentDate.getDate() + 
										'</td>' +
									'</tr>' +
								'</table>' +
							'</td>';
			
			// End row
			if (currentDate.getDay() == 6)
				contentDates += '</tr>';
		}
		
		return contentDates;
	},
	
	/**
	 * This public function handles the render of the calendar date.
	 */
	renderContentDate: function(span, row) {
		if (span.innerHTML.length > 0)
			span.innerHTML += "<br>";
		
		// Only if administration
		if (this.parameters.administrator)
			this.renderContentDateAdmin(span, row);
		else {
			if (row.Party == false) {
				this.renderContentDateUser(span, row);
			}
		}
	},
	
	/**
	 * This public function handles the render of the calendar date for administrators.
	 */
	renderContentDateAdmin: function(span, row) {
		if (row.Party == true) {
			span.innerHTML += '<a style="color: navy;" href="/admin/Session/Session.aspx?SessionDateId=' + row.SessionDateId + '">' +
									formatTitle(row.StartDate) +
								'</a>';
		} else {
			span.innerHTML += '<a href="/admin/Session/Session.aspx?SessionDateId=' + row.SessionDateId + '">' +
									formatTitle(row.StartDate) +
								'</a>';
		}
	},
	
	/**
	 * This public function handles the render of the calendar date for users.
	 */
	renderContentDateUser: function(span, row) {
			span.innerHTML += '<a href="#" onclick="' + this.getName() +  '.onUserClick(' + row.SessionDateId + ', ' + row.StartDate.getTime() + '); return false;">' +
								formatTitle(row.StartDate) +
							'</a>';
	},
	
	/**
	 * This public function handles the render of the create session.
	 */
	renderCreateSession: function(date) {
		var span = $(getDateId(date));
		
		this.removeCreateSession();
		
		span.innerHTML += '<span id="createSession">' +
								((span.innerHTML.length > 0) ? '<br>' : '') +
								'<a href="/admin/Session/Session.aspx?StartDate=' + getDate(date) + '" onClick="' + this.getName() + '.removeCreateSession()">Create..</a>' +
							'</span>';
	},
	
	/**
	 * This public function handles the remove of the create session.
	 */
	removeCreateSession: function() {
		var createSession = $('createSession');
		
		if (createSession)
			createSession.remove();
	},
	
	/**
	 * This public function handles the colour calendar date routine.
	 */
	colourCalendarDate: function(date) {
		var element = $('_' + getDateId(date));
		
		if (element) {
			// Render weekend style
			if (date.getTime() == this.variables.selectedDate.getTime()) {
				element.className = 'Selected';
				
				// Only if administration
				if (this.parameters.administrator)
					this.renderCreateSession(date);
			}
			else if (date.getMonth() != this.getCalendarMonth())
				element.className = 'NotAvailable';
			else
				element.className = '';
		}
	},
	
	/**
	 * This public function handles the date click event.
	 */
	onDateClick: function(time) {
		// Previous date
		previousDate = this.variables.selectedDate;
		
		// Select current date
		this.variables.selectedDate = new Date(time);
		
		// this.removeCreateSession();
		
		this.colourCalendarDate(this.variables.selectedDate);
		this.colourCalendarDate(previousDate);
	},
	
	/**
	 * This public function handles the administrator click event.
	 */
	onAdminClick: function(sessionId, time) {
		/* var sessionDates = eval(CalendarView.GetCalendarSession(sessionId).value);
		var date = new Date(time);
		
		if (sessionDates.Rows.length > 0) {
			var session = sessionDates.Rows[0];
			
			Dialog.alert('<p><strong>' + session.Name + '</strong></p>' +
						'<table cellpadding="9" cellspacing="4" border="0" width="60%" style="text-align:left">' +
							'<tr><td>Please select from the following actions:</td></tr>' +
							'<tr><td>&nbsp;</td></tr>' +
							'<tr><td><a href="/admin/Session/Session.aspx?SessionDateId=' + session.SessionDateId + '">Edit Existing Session</a></td></tr>' +
							'<tr><td><a href="/admin/Session/Session.aspx?StartDate=' + getDate(date) + '">Create New Session</a></tr></tr>' +
						'</table>',
				{
					id: "myAlertDetails",
					windowParameters: {
						className: "alphacube",
						showEffect: Effect.Appear,
						width: 400,
						height: 175
					},
					okLabel: "Close"
				} );
		} */
	},

	/**
	 * This public function handles the user click event.
	 */
	onUserClick: function(sessionId, time) {
		/* var sessionDates = eval(CalendarView.GetCalendarSession(sessionId).value);
		var currentDate = new Date();
		var date = new Date(time);
		
		if (sessionDates.Rows.length > 0) {
			var session = sessionDates.Rows[0];
			
			if (session.StartDate <= currentDate) {
				Dialog.alert('<p><strong>' + session.Name + '</strong></p>' +
								'<p>You can not register for completed sessions!</p>' +
								'<p>Please select another session from the calendar.</p>',
					{
						id: "myAlert",
						windowParameters: {
							className: "alphacube",
							showEffect: Effect.Appear,
							width: 400
						}
					} );
			} else if (((session.StartDate.getTime() - currentDate.getTime()) / (1000 * 60 * 60 * 24)) < 3) {
				Dialog.confirm('<p><strong>' + session.Name + '</strong></p>' +
								'<p>This session has reached the 72 hour minimum notice for registration.</p>' +
								'<p>Please contact the administrators or select another session from the calendar.</p>' +
								'<br/>' +
								'<p>If you have the registration password please enter it below:</p>' +
								"<p><span id='registrationErrorMsg' class='validation' style='display:none; font-weight: bold;'>&nbsp;</span></p>" +
								'<p><input type="password" id="txtRegistrationPassword" style="width: 180px;" /></p>',
					{
						id: "myRegister",
						windowParameters: {
							className: "alphacube",
							showEffect: Effect.Appear,
							width: 500
						},
						okLabel: "Register",
						ok: function(win) {
							if ($('txtRegistrationPassword').value == session.Password) {
								document.location = "Registration.aspx?SessionDateId=" + session.SessionDateId;
								
								return true;
							}
							$('registrationErrorMsg').innerHTML = 'Registration password incorrect!';
							$('registrationErrorMsg').show();
							
							Windows.focusedWindow.updateHeight();
							new Effect.Shake(Windows.focusedWindow.getId());
							
							return false;
						},
						cancelLabel: "Cancel"
					} );
			} else if (session.AttendeeMax > 0 && session.Attendees >= session.AttendeeMax) {
				Dialog.confirm('<p><strong>' + session.Name + '</strong></p>' +
								'<p>This session has currently reached the maximum attendees available.</p>' +
								'<p>Please contact the administrators or select another session from the calendar.</p>' +
								'<br/>' +
								'<p>If you have the registration password please enter it below:</p>' +
								"<p><span id='registrationErrorMsg' class='validation' style='display:none; font-weight: bold;'>&nbsp;</span></p>" +
								'<p><input type="password" id="txtRegistrationPassword" style="width: 180px;" /></p>',
					{
						id: "myRegister",
						windowParameters: {
							className: "alphacube",
							showEffect: Effect.Appear,
							width: 500
						},
						okLabel: "Register",
						ok: function(win) {
							if ($('txtRegistrationPassword').value == session.Password) {
								document.location = "Registration.aspx?SessionDateId=" + session.SessionDateId;
								
								return true;
							}
							$('registrationErrorMsg').innerHTML = 'Registration password incorrect!';
							$('registrationErrorMsg').show();
							
							Windows.focusedWindow.updateHeight();
							new Effect.Shake(Windows.focusedWindow.getId());
							
							return false;
						},
						cancelLabel: "Cancel"
					} );
			} else {
				Dialog.confirm('<p><strong>' + session.Name + '</strong></p>' +
							'<p>Would you like to register for this session?</p>',
					{
						id: "myConfirm",
						windowParameters: {
							className: "alphacube",
							showEffect: Effect.Appear,
							width: 400
						},
						okLabel: "Continue",
						ok: function(win) {
							document.location = "Registration.aspx?SessionDateId=" + session.SessionDateId;
							return true;
						},
						cancelLabel: "Cancel"
					} );
			}
		} */
	},
	
	/**
	 * This public function handles the user previous click.
	 */
	onPreviousClick: function() {
		this.parameters.currentDate = new Date(this.getCalendarYear(), this.getCalendarMonth() - 1, 1);
		
		this.render();
	},
	
	/**
	 * This public function handles the user next click.
	 */
	onNextClick: function() {
		this.parameters.currentDate = new Date(this.getCalendarYear(), this.getCalendarMonth() + 1, 1);
		
		this.render();
	}
	
}

/**
 * This public function handles the conversion of date to string.
 */
function getDateId(date) {
	var result = (date.getMonth() + 1) + '_' +
				date.getDate() + '_' +
				date.getFullYear();
	
	return result;
}

/**
 * This public function handles the conversion of date to string.
 */
function getDate(date) {
	var result = (date.getMonth() + 1) + '/' +
				date.getDate() + '/' +
				date.getFullYear();
	
	return result;
}

/**
 * This public function handles the format of the title.
 */
function formatTitle(date) {
	var hours = date.getHours();
	var minutes = date.getMinutes();
	var meridian = (hours >= 12 ? 'PM' : 'AM');
	var title = '';
	
	if (hours > 12)
		hours -= 12;
	
	if (hours == 0)
		hours = 12;
	
	if (minutes < 10)
		minutes = '0' + minutes;
	
	title = hours + ':' + minutes + ' ' + meridian;
	
	return title;
}