Figment.Import('Figment.Date',Figment.getJSRoot() + '_framework/');
Figment.Import('Figment.DOM',Figment.getJSRoot() + '_framework/');
Figment.Import('Figment.EventHandler',Figment.getJSRoot() + '_framework/');

/**
 * Creates a Calendar widget to assist in the selection of dates from form 
 * fields in an HTML document.
 */
Figment.Namespace("Disney.WDPRO.UI.Widgets.Calendar");

/**
 * Main shared class that manages the calendars and provides helper methods for
 * creating and locating calendars in the document.
 * 
 * TODO: Need to add the default action of updating an associated input field
 * for a calendar.
 * 
 * @requires Figment.EventHandler
 * @type Disney.WDPRO.UI.Widgets.Calendar
 * @constructor
 * @fileoverview 	Main shared class that manages the calendars and provides 
 * 				helper methods for creating and locating calendars in the 
 * 				document.
 */
Disney.WDPRO.UI.Widgets.Calendar = {
	/**
	 * Keeps track of all the calendar objects in the document
	 * @type Array[](Disney.WDPRO.UI.Widgets.Calendar.Container)
	 * @private
	 */
	containers: [],
	
	/**
	 * Constants
	 * @private
	 */
	CONST_SHOW_CALENDAR_CLASSNAME: 'calendarShow',
	/**
	 * Constants
	 * @private
	 */
	CONST_CALENDAR_CONTAINER_CLASSNAME: 'calendarContainer',
	
	CONST_CALENDAR_DIV_CONTAINER_CLASSNAME: 'calendarTableContainer',
	
	main: function ()
	{
		Disney.WDPRO.UI.Widgets.Calendar.createCalendars();
	},
	
	/**
	 * Scan the document and replace any <OBJECT> that reference a calendar
	 * widget with the actual calendar widget.  It will use the <OBJECT> params
	 * to build the calendar with the approriate settings.
	 */
	createCalendars: function()
	{
		// Search for all calendar widgets on the page
		var listOfWidgets = Figment.DOM.getElementsByClassName('calendarWidget');
		var listOfWidgetsLength = listOfWidgets.length;
		var i = 0;
		var calendarWidget;
		var objElement,targetElement;
		
		for( i=0; i < listOfWidgetsLength; i++ )
		{
			objElement = listOfWidgets[i];
			// Get the id of the field this calendar is attached to
			targetElement = document.getElementById(objElement.id.substring(0,objElement.id.indexOf("_cal")));
			if( targetElement !== null )
			{
				// Create a calendar widget for this container
				calendarWidget = Disney.WDPRO.UI.Widgets.Calendar.createCalendar(objElement.id + "_widget",targetElement,objElement);
				// Attach on click event to show this calendar when the place holder
				// icon is clicked
				Figment.EventHandler.addEvent( objElement,'click',Disney.WDPRO.UI.Widgets.Calendar.EVENT_calendarIcon_onClick );
				Figment.EventHandler.addEvent( targetElement,'click',Disney.WDPRO.UI.Widgets.Calendar.EVENT_inputField_onFocus );
				Figment.EventHandler.addEvent( targetElement,'keyup',Disney.WDPRO.UI.Widgets.Calendar.EVENT_inputField_onFocus );
			}
		}
		
		// Attach event to document for handling the auto-close of the calendars
		Figment.EventHandler.addEvent( document,'click',Disney.WDPRO.UI.Widgets.Calendar.EVENT_document_onClick );
		Figment.EventHandler.addEvent( document,'keyup',Disney.WDPRO.UI.Widgets.Calendar.EVENT_document_onClick );
				
		delete calendarWidget;
		delete listOfWidgets; 
	},
	
	/**
	 * Given an element inside a calendar, it will locate the parent table and
	 * return the associated calendar object.
	 * @param {HTMLElement} element
	 * @return {Disney.WDPRO.UI.Widgets.Calendar.Container}
	 */
	findCalendar: function(element)
	{
		var id;
		var containers;
		var container;
		var calendarWidget = null;
		var i;
		var div;
		
		if( element !== null && element.nodeType === 1 )
		{
			while( element.nodeName.toLowerCase() !== 'table' )
			{
				element = element.parentNode;
				if( element !== null )
				{
					if( element.nodeName.toLowerCase() === 'body' )
					{
						// Wow, we went far...and still no table...ugh
						element = null;
						break;
					}
				}
				else
				{
					break;
				}
			}
			
			if( element !== null )
			{
				div = element.parentNode;
				// Get all the calendar containers
				containers = Disney.WDPRO.UI.Widgets.Calendar.containers;
				for( i=0; i < containers.length; i++ )
				{
					container = containers[i];
					if( container !== null )
					{
						// Compare the id's
						if( container.getId() === div.id )
						{
							// Return the calendar that we found that matches
							calendarWidget = container;
							break;
						}
					}
				}
			}
		}
		
		delete div;
		delete container;
		delete containers;
		
		// Unable to find the calendar
		return calendarWidget;
	},
	
	/**
	 * Retrieves the calendar that is associated with the dom element that was
	 * clicked.
	 * @return {Disney.WDPRO.UI.Widgets.Calendar.Container}
	 */
	getAssociatedCalendar: function(domElement)
	{
		var containers;
		var i;
		var targetElement;
		var calendarWidget = null;
		
		if( domElement !== null )
		{
			// Get the id of the field this calendar is attached to
			targetElement = document.getElementById(domElement.id.substring(0,domElement.id.indexOf("_cal")));
		  
		}
		if( targetElement !== null )
		{
			// Get all the calendar containers
			containers = Disney.WDPRO.UI.Widgets.Calendar.containers;
			
			for( i=0; i < containers.length; i++ )
			{    
			
			     
				calendarWidget = containers[i];
				
				if( calendarWidget !== null )
				{
					if( calendarWidget.getTarget() === targetElement )
					{
						break;
					}
				}
			}
		}
		
		delete targetElement;
		delete containers;
		
		return calendarWidget;
	},
	
	hideAll: function()
	{
		var containers;
		var calendarWidget;
		
		// Hide all calendars
		// Get all the calendar containers
		containers = Disney.WDPRO.UI.Widgets.Calendar.containers;
		for( i=0; i < containers.length; i++ )
		{
			calendarWidget = containers[i];
			if( calendarWidget !== null )
			{
				calendarWidget.hide();
			}
		}
		
		delete calendarWidget;
		delete containers;
	},
	
	/**
	 * Event to fire when the "Next" month button is pressed.  It will change
	 * the calendar to the month previous to one currently displayed.
	 * @param {Event} evt	if an event object is based in (W3C event model)
	 * @private
	 */
	EVENT_calendarForward_onClick: function(evt)
	{
		var windowEvent = Figment.EventHandler.getEvent(evt);
		var element = windowEvent.element;
		var calendar;
		var date;
		
		// Get the calendar that this button belongs to
		calendar = Disney.WDPRO.UI.Widgets.Calendar.findCalendar(element);
		if( calendar !== null )
		{
			// Get the current month it is displaying
			date = calendar.getCurrentMonth();
			// Increment the month to the next month
			calendar.goToMonth(Figment.Date.add(date,"M",1));
		}
		windowEvent.stopEvents();
		
		delete date;
		delete windowEvent.element;
		delete windowEvent.targetElement;
		delete element;
		delete windowEvent;
		delete calendar;
	},
	
	/**
	 * Event to fire when the "Back" month button is pressed.  It will change
	 * the calendar to the month previous to one currently displayed.
	 * @param {Event} evt	if an event object is based in (W3C event model)
	 * @private
	 */
	EVENT_calendarBack_onClick: function(evt)
	{
		var windowEvent = Figment.EventHandler.getEvent(evt);
		var element = windowEvent.element;
		var calendar;
		var date;
		
		// Get the calendar that this button belongs to
		calendar = Disney.WDPRO.UI.Widgets.Calendar.findCalendar(element);
		if( calendar !== null )
		{
			// Get the current month it is displaying
			date = calendar.getCurrentMonth();
			// Decrement the month to the previous month
			calendar.goToMonth(Figment.Date.subtract(date,"M",1));
		}
		windowEvent.stopEvents();
		
		delete date;
		delete windowEvent.element;
		delete windowEvent.targetElement;
		delete element;
		delete windowEvent;
		delete calendar;
	},
		
	EVENT_inputField_onFocus: function(evt)
	{
		var windowEvent = Figment.EventHandler.getEvent(evt);
		var element = windowEvent.element;
		var calendar;
		
		Disney.WDPRO.UI.Widgets.Calendar.hideAll();
		
		// Get the calendar that this button belongs to
		calendar = Disney.WDPRO.UI.Widgets.Calendar.getAssociatedCalendar(Figment.DOM.getNextSibling(element));
		if( calendar !== null )
		{
			calendar.show();
		}
		windowEvent.preventDefault();
		windowEvent.stopEvents();
		
		delete windowEvent.element;
		delete windowEvent.targetElement;
		delete element;
		delete windowEvent;
	},
	
	/**
	 * Event to fire when the calendar icon is clicked by the guest.
	 * @param {Event} evt	if an event object is based in (W3C event model)
	 */
	EVENT_calendarIcon_onClick: function(evt)
	{
		var windowEvent = Figment.EventHandler.getEvent(evt);
		var element = windowEvent.element;
		var calendar;
		
		Disney.WDPRO.UI.Widgets.Calendar.hideAll();
		
		// Get the calendar that this button belongs to
		calendar = Disney.WDPRO.UI.Widgets.Calendar.getAssociatedCalendar(element);
		if( calendar !== null )
		{
			calendar.show();
		}
		windowEvent.preventDefault();
		windowEvent.stopEvents();
		
		delete windowEvent.element;
		delete windowEvent.targetElement;
		delete element;
		delete windowEvent;
	},
	
	/**
	 * Event to fire when the document is clicked.
	 * @param {Event} evt	if an event object is based in (W3C event model)
	 */
	EVENT_document_onClick: function(evt)
	{
		var windowEvent = Figment.EventHandler.getEvent(evt);
		var element = windowEvent.targetElement;
		var calendar;
		var containers;
		var calendarWidget;
		
		// Get the calendar that this button belongs to
		calendarWidget = Disney.WDPRO.UI.Widgets.Calendar.findCalendar(element);
		if( calendarWidget === null )
		{
			Disney.WDPRO.UI.Widgets.Calendar.hideAll();
		}
		
		delete windowEvent.element;
		delete windowEvent.targetElement;
		delete element;
		delete windowEvent;
		delete containers;
		delete calendarWidget;
	},
	
	/**
	 * Create a new calendar container with the id specified.  Creates all the
	 * HTML required to render the calendar widget.
	 * @param {String} id
	 * @return {Disney.WDPRO.UI.Widgets.Calendar.Container}
	 */
	createCalendar: function(id,inputTarget,launcher)
	{
		var calendar = new Disney.WDPRO.UI.Widgets.Calendar.Container(id,inputTarget,launcher);
		// Add this calendar to the list in the shared space
		Disney.WDPRO.UI.Widgets.Calendar.containers.push(calendar);
		return calendar;
	}
};

/**
 * Class that is created for each calendar widget desired for the current
 * document.
 * @member Disney.WDPRO.UI.Widgets.Calendar
 * @requires Figment.DOM
 * @requires Figment.Date
 * @constructor
 */
Disney.WDPRO.UI.Widgets.Calendar.Container = Figment.Class();
Disney.WDPRO.UI.Widgets.Calendar.Container.prototype = {
	/**
	 * Constructor
	 * @param {String} id
	 */
	initialize: function(id,inputTarget,launcher)
	{
		this.id = id;
		this.cells = []; // Stores cell objects for each day in the current month
		this.currentMonth = Figment.Date.findMonthStart(new Date());
		this.selectedDays = []; // Stores the date objects
		this.todayClass = 'today';
		this.pastDayClass = 'dayInPast';
		this.dayNotAvailableClass = 'dayNotAvailable';
		this.target = inputTarget;
		this.launcher = launcher;
		this.calendarOptions = {};
		// Create an anonymous function to handle the default onclick event
		this.defaultAction = function(evt)
		{
			var windowEvent = Figment.EventHandler.getEvent(evt);
			var element = windowEvent.element;
			var calendarWidget = Disney.WDPRO.UI.Widgets.Calendar.findCalendar(element);
			var fieldTarget = null;
			var dateOfElement;
			if( calendarWidget !== null )
			{
				// Get the calendar target field
				fieldTarget = calendarWidget.getTarget();
				// Check to be sure this target is a form input field
				if( fieldTarget !== null && fieldTarget.nodeName.toLowerCase() === 'input' && fieldTarget.getAttribute("type") === 'text' )
				{
					// Get the event element title
					dateOfElement = element.parentNode.title;
					// Change the field to use this date
					fieldTarget.value = dateOfElement;
					// Now hide the calendar
					calendarWidget.hide();
					// Make sure to fire the change event on the input field
					Figment.EventHandler.fireEvent(fieldTarget,'change');
					Figment.EventHandler.fireEvent(fieldTarget,'blur');
				}
				windowEvent.preventDefault();
				windowEvent.stopEvents();
			}
			
			// Cleanup after ourselves
			Figment.EventHandler.cleanUp(windowEvent);
			delete element;
			delete fieldTarget;
			delete calendarWidget;
		};
	},
	/**
	 * Get the input element that the calendar provides values for.
	 * @return {HTMLInputElement}
	 */
	getTarget: function()
	{
		if( typeof this.target === 'undefined' )
		{
			this.target = null;
		}
		return this.target;
	},
	
	/**
	 * Get the element that triggered the calendar to display.
	 * @return {IHTMLElement}
	 */
	getLauncher: function()
	{
		if( typeof this.launcher === 'undefined' )
		{
			this.launcher = null;
		}
		return this.launcher;
	},
	
	/**
	 * Change the class name that marks today's date.
	 * @param {String} className
	 */
	setTodayClass: function(className)
	{
		var cell;
		// Get today's cell
		cell = this.getTodaysCell();
		if( cell !== null )
		{
			cell.addClassName(className);
		}
		this.todayClass = className;
	},
	
	/**
	 * Get the current class name used for marking today's date.
	 * @return {String}
	 */
	getTodayClass: function()
	{
		return this.todayClass;
	},
	
	/**
	 * Creates the HTML shell for the calendar.
	 * @private
	 */
	createShell: function()
	{
		var table;
		var tbody;
		var thead;
		var div;
		
		div = document.createElement('div');
		div.className = Disney.WDPRO.UI.Widgets.Calendar.CONST_CALENDAR_DIV_CONTAINER_CLASSNAME;
		div.id=this.id;
		table = document.createElement('table');
		
		thead = document.createElement('thead');
		table.appendChild(thead);
		
		tbody = document.createElement('tbody');
		table.appendChild(tbody);
		// Add the table to the div
		div.appendChild(table);
		
		Figment.DOM.addClassName(table,Disney.WDPRO.UI.Widgets.Calendar.CONST_CALENDAR_CONTAINER_CLASSNAME);
		if( this.getLauncher() )
		{
			// We don't care about siblings since we're putting the
			// calendar inside the target 
			this.getLauncher().appendChild(div);
		}
		
		delete thead;
		delete tbody;
		delete table;
	},
	
	/**
	 * Get the id for this calendar.  The id is also used in generating the 
	 * HTML for the calendar.
	 * @return {String}
	 */
	getId: function()
	{
		return this.id;
	},
	
	/**
	 * Change the default action for all cells (days).  This the event that will
	 * be fired when the cell is clicked.
	 * @param {Function} action
	 */
	changeDefaultAction: function(action)
	{
		// Initialize
		var cell;
		var i;
		
		for( i=0; i < this.cells.length; i++ )
		{
			cell = this.cells[i];
			// Only change the actions on the cells currently using the default
			// action
			if( cell.action === this.defaultAction )
			{
				// Change the action to the new default
				cell.action = action;
				// Re-render the cell
				renderCell(cell);
			}
		}
		// Set the default action for use later
		this.defaultAction = action;
		delete cell;
	},
	
	/**
	 * Create or change the HTML for the header portion of the calendar.
	 * @private
	 */
	renderTitleBar: function()
	{
		// Use the current month and year
		var tHead;
		var row;
		var th;
		var navMonth;
		var container;
		var div;
		
		div = document.getElementById(this.id);
		if( div !== null )
		{
			// Get the header for this table
			tHead = div.firstChild.firstChild;
			
			// Create title bar for the first time?
			if( tHead == null || tHead.rows.length == 0 )
			{
				// Added null check above and following to catch the error being thrown by Safari
				if (tHead == null){
					tHead = div.firstChild.createTHead();
				}
				// Create new row
				row = document.createElement('tr');
				
				// Create header cell for the back navigation
				th = document.createElement('th');
				// CREATE BACK NAV BUTTON
				// Get the previous month
				navMonth = Figment.Date.subtract(this.currentMonth,"M",1);
				// Set the title for this cell
				th.setAttribute('title','Go to ' + Figment.Date.dateToString(navMonth,'MMMM yyyy'));
				container = document.createElement('div');
				// Add a class for this div
				Figment.DOM.addClassName(container,'backArrow');
				// Create "faux" back arrow using UTF code for «
				container.appendChild(document.createTextNode('\u00AB'));
				// Attach event to move the calendar back one month
				Figment.EventHandler.addEvent(container,'click',Disney.WDPRO.UI.Widgets.Calendar.EVENT_calendarBack_onClick);
				// Add the container to the cell
				th.appendChild(container);
				// Add the nav button to the row
				row.appendChild(th);
			
				// Create header cell for the month/year title
				th = document.createElement('th');
				// Set the title for this cell
				th.setAttribute('title',Figment.Date.dateToString(this.currentMonth,'MMMM yyyy'));
				// Set the column span for this cell (should take up 5 days worth of cells)
				th.setAttribute('colSpan','5');
				container = document.createElement('div');
				container.appendChild(document.createTextNode(Figment.Date.dateToString(this.currentMonth,'MMMM yyyy')));
				// Add the container to the cell
				th.appendChild(container);
				// Add the nav button to the row
				row.appendChild(th);
				
				// CREATE FORWARD NAV BUTTON
				// Create header cell for the back navigation
				th = document.createElement('th');
				// Get the next month
				navMonth = Figment.Date.add(this.currentMonth,"M",1);
				// Set the title for this cell
				th.setAttribute('title','Go to ' + Figment.Date.dateToString(navMonth,'MMMM yyyy'));
				container = document.createElement('div');
				// Add a class for this div
				Figment.DOM.addClassName(container,'forwardArrow');
				// Create "faux" forward arrow using UTF code for »
				container.appendChild(document.createTextNode('\u00BB'));
				// Attach event to move the calendar forward one month
				Figment.EventHandler.addEvent(container,'click',Disney.WDPRO.UI.Widgets.Calendar.EVENT_calendarForward_onClick);
				// Add the container to the cell
				th.appendChild(container);
				// Add the nav button to the row
				row.appendChild(th);
				
				// Add the row to the header
				tHead.appendChild(row);
				
				// Now add the Day headers
				// Create new row
				row = document.createElement('tr');
				for( i=0; i < Figment.Date.CONST_WEEKDAYS_SHORT.length; i++ )
				{
					// Create header cell for this weekday
					th = document.createElement('th');
					container = document.createElement('div');
					// Add a class for this div
					Figment.DOM.addClassName(container,'dayHeader');
					// Create text for the current weekday
					container.appendChild(document.createTextNode(Figment.Date.CONST_WEEKDAYS_SHORT[i]));
					// Add the container to the cell
					th.appendChild(container);
					// Add the weekday header to the row
					row.appendChild(th);
				}
				
				// Add the row to the header
				tHead.appendChild(row);
			}
			else	// Update the title bar
			{
				// Get the cell that contains the back button
				th = tHead.rows[0].firstChild;
				// Get the previous month
				navMonth = Figment.Date.subtract(this.currentMonth,"M",1);
				// Update the title of the back button
				th.setAttribute('title','Go to ' + Figment.Date.dateToString(navMonth,'MMMM yyyy'));
				
				// Get the cell that contains the month/year of the calendar
				th = tHead.rows[0].childNodes[1];
				// Change the title to reflect the new month/year
				th.setAttribute('title',Figment.Date.dateToString(this.currentMonth,'MMMM yyyy'));
				// Change the text to display the new month/year
				th.firstChild.firstChild.nodeValue = th.getAttribute("title");
				
				// Get the cell that contains the forward button
				th = tHead.rows[0].lastChild;
				// Get the next month
				navMonth = Figment.Date.add(this.currentMonth,"M",1);
				// Update the title of the back button
				th.setAttribute('title','Go to ' + Figment.Date.dateToString(navMonth,'MMMM yyyy'));
			}
		}
		
		div = null;
	},
	
	/**
	 * Get the current date object for the month displayed by the calendar.
	 * @return {Date}
	 */
	getCurrentMonth: function()
	{
		return this.currentMonth;	
	},
	
	/**
	 * Change the calendar to the month that the specified date is part of.
	 * @param {Date} date
	 */
	goToMonth: function(date)
	{
		// Change the month and year
		this.currentMonth = Figment.Date.findMonthStart(date);
		// Re-render the entire calendar
		this.refresh();
	},
	
	/**
	 * Get the cell that represents today's date.
	 * @return {Disney.WDPRO.UI.Widgets.Calendar.Cell}
	 */
	getTodaysCell: function()
	{
		var numDaysPrior;
		var totalDays;
		var cell;
		// Determine if we are viewing the current month
		if( this.currentMonth === Figment.Date.findMonthStart(new Date()) )
		{
			numDaysPrior = Figment.Date.findMonthStart(this.currentMonth).getDay();
			// Add the number of days plus today's date
			totalDays = numDaysPrior + new Date().getDate();
			// Now get the cell
			cell = this.cells[totalDays];
		}
		return cell;
	},
	
	/**
	 * Creates or updates all HTML for the cells in the calendar table.
	 * @private
	 */
	render: function()
	{
		// Initialize
		var cell;
		var i;
		var row;
		var num;
		var tBody;
		var numDaysPrior;
		var lastDayOfMonth;
		var inputDate = null;
		var input = null;
		var container = null;
		
		container = document.getElementById(this.id);
		if( container === null )
		{
			// Create the container for this calendar
			this.createShell();
			container = document.getElementById(this.id);
		}
		
		// Get the table body that contains the rows for calendar cells
		tBody = container.firstChild.tBodies[0];
		
		// Use the current month & year to render the cells
		this.renderTitleBar();
		
		// Clear the current cells array
		this.cells.clear();
		if( tBody.childNodes.length > 0 )
		{
			while( tBody.hasChildNodes() )
			{
				tBody.removeChild(tBody.firstChild);
			}
		}
		
		numDaysPrior = Figment.Date.findMonthStart(this.currentMonth).getDay();
		lastDayOfMonth = Figment.Date.findMonthEnd(this.currentMonth).getDate();
		
		// Create empty cells for 6 weeks (will cover every calendar month size)
		for( i=0; i < 42; i++  )
		{
			if( i < numDaysPrior )
			{
				// Blank day for days prior to start of this month
				this.cells.push(new Disney.WDPRO.UI.Widgets.Calendar.Cell());
			}
			else if( i < (numDaysPrior + lastDayOfMonth) )
			{
				// Create cell for the current day in this month
				this.cells.push(new Disney.WDPRO.UI.Widgets.Calendar.Cell(Figment.Date.add(this.currentMonth,'D',i-numDaysPrior)));
			}
			else
			{
				// Blank day for days after the end of this month
				this.cells.push(new Disney.WDPRO.UI.Widgets.Calendar.Cell());
			}
		}
		
		num = 0;
		for( i=0; i < this.cells.length; i++ )	
		{
			cell = this.cells[i];
			if( (i > 6) && (i%7) === 0 )
			{
				num += 1;	
			}
			// what row should this cell be placed in
			if( num >= tBody.rows.length )
			{
				// Need to create a new row for the next 7 cells
				row = document.createElement('tr');
				// Add the row to the table body
				container.firstChild.tBodies[0].appendChild(row);
			}
			else
			{
				// Get the existing row from the rows array
				row = tBody.rows[num];
			}
			if( cell.date !== null )
			{
				cell.action = this.defaultAction;
				if( this.isRestrictedDate(cell.date)){
					//retrict this date
					//dayNotAvailableClass
					cell.addClassName(this.pastDayClass);
                    cell.action = null;
				}
				else if( Figment.Date.compare(cell.date,new Date()) )
                {
                    // Add the class for today's date
                    cell.addClassName(this.todayClass);
                }
				else if( Figment.Date.before(cell.date,new Date() ) )
                {
                    // Add the class for a day in the past
                    cell.addClassName(this.pastDayClass);
                    cell.action = null;
                }
			}
			// Render this cell
			this.renderCell(cell,row);
		}
		
		delete container;
		delete inputDate;
		delete input;
		delete row;
		delete cell;
		delete tBody;
	},
	
	/**
	 * Refreshs the calendar when one of the navigation buttons has been
	 * pressed.
	 */
	refresh: function()
	{
		// Refresh is just a convience method...
		this.render();
	},
	
	/**
	 * Changes the HTML for the cell (day) specified. Usually called when a
	 * day needs to have a different event trigger or CSS class names 
	 * associated with it.
	 * @param {Cell} cell
	 */
	changeCell: function(cell)
	{
		//Initialize
		var i;
		
		for( i=0; i < this.cells.length; i++ )
		{
			switch( this.cells[i].date )
			{
				case cell.date:
					// Switch out the current cell with this new one
					this.cells[i] = cell;
					// Re-render the specified cell
					renderCell(cell);
					return;
			}
		}
	},
	
	/**
	 * Creates the HTML for an individual cell in the calendar table.
	 * @param {Cell} cell
	 * @private
	 */
	renderCell: function(cell)
	{
		// Initialize
		var columnToReplace = null;
		var column = null;
		var day = null;
		var i = null;
		var row = null;
		
		// Create a new column for this cell
		column = document.createElement('td');
		if( cell.date !== null )
		{
			column.setAttribute('id','date_'+Figment.Date.dateToString(cell.date,'M_d_yyyy')+'for'+this.id);
			column.setAttribute('title',Figment.Date.dateToString(cell.date,'M/d/yyyy'));
		}
		else
		{
			// Add an id for this blank
			Figment.DOM.addClassName(column,'blankCell');
		}
		// Add a new container for the styling, event, and numeric value
		day = document.createElement('div');
		for( i=0; i < cell.classes.length; i++ )
		{
			// Add the css class to the cell
			Figment.DOM.addClassName(day,cell.classes[i]);
		}
		if( cell.action !== null )
		{
			// Add the event for this cell
			Figment.EventHandler.addEvent(day,'click',cell.action);
		}
		if( cell.date !== null )
		{
			// Add the numeric value for the day to the cell
			day.appendChild(document.createTextNode(cell.date.getDate()));
		}
		else
		{
			// Add a blank day
			day.appendChild(document.createTextNode('\u00A0'));
		}
		// Add the data to the column for the cell
		column.appendChild(day);
		if( cell.date !== null )
		{
			// Get the current cell for this date from the document
			columnToReplace = document.getElementById(Figment.Date.dateToString(cell.date,'M_d_yyyy')+'for'+this.id);
		}
		if( columnToReplace !== null )
		{
			// Replace the current cell with the new one
			columnToReplace.parentNode.replaceChild(column,columnToReplace);
		}
		else
		{
			// This is the initial rendering of this cell...so let's use a
			// non-specified argument for the row container that is used only
			// at initial render
			if( arguments.length > 1 )
			{
				// Get the containing row
				row = arguments[1];
				if( row !== null )
				{
					// Add the column to this row
					row.appendChild(column);
				}
			}
		}
		
		delete columnToReplace;
		delete day;
		delete column;
		delete row;
	},
	
	/**
	 * Make sure this calendar is displaying to the guest.
	 */
	show: function()
	{
		// Attempt to get the value of the target input as a date
		var input = this.getTarget();
		var inputDate;
		var domElement;
		
		try {
			if( input !== null )
			{
				// Parse value
				inputDate = Figment.Date.createDate(input.value);
				
				if( inputDate !== null && !isNaN( inputDate.getTime() )  )
				{
					inputDate = Figment.Date.subtract(inputDate,"M",1);
					this.currentMonth = Figment.Date.findMonthStart(inputDate);
				}
				// Removed since this only seems to cause the calendar to NOT work.
				//else
				//{
					//inputDate = Figment.Date.createDate( new Date() );
					//inputDate = Figment.Date.subtract( inputDate,"M",1);
					//this.currentMonth = Figment.Date.findMonthStart(new Date());
				//}
			}
			this.render();
			domElement = document.getElementById( this.id );
			if( domElement !== null )
			{
				if( !Figment.DOM.hasClassName( domElement,Disney.WDPRO.UI.Widgets.Calendar.CONST_SHOW_CALENDAR_CLASSNAME ) )
				{
					Figment.DOM.addClassName( domElement,Disney.WDPRO.UI.Widgets.Calendar.CONST_SHOW_CALENDAR_CLASSNAME );
					Disney.WDPRO.UI.Widgets.Calendar.Container.prototype.toggleSelectBoxes();
				}
			}
		} catch( error ) { // for the time being, do nothing
			alert( error )
		} finally {
			delete inputDate;
			delete input;
			delete domElement;
		}
	},
	
	/**
	 * Make sure this calendar is no longer displayed to the guest.
	 */
	hide: function()
	{
		var domElement = document.getElementById( this.id );
		if( domElement !== null )
		{
			if( Figment.DOM.hasClassName( domElement,Disney.WDPRO.UI.Widgets.Calendar.CONST_SHOW_CALENDAR_CLASSNAME ) )
			{
				Figment.DOM.removeClassName( domElement,Disney.WDPRO.UI.Widgets.Calendar.CONST_SHOW_CALENDAR_CLASSNAME );
				Disney.WDPRO.UI.Widgets.Calendar.Container.prototype.toggleSelectBoxes();
			}
		}
		
		delete domElement;
	},
		
	/**
	 * Hide select boxes in order to prevent unsightly boxes showing through
	 * the blocking layer. Used to fix IE :-(.
	 */
	toggleSelectBoxes: function()
	{
		var objBody	= Figment.DOM.getElementsByTagName( "body" )[0];

		if( Figment.DOM.hasClassName( objBody, 'hideSelects' ))
		{
			Figment.DOM.removeClassName( objBody, 'hideSelects' );
		}
		else
		{
			Figment.DOM.addClassName( objBody, 'hideSelects' );
		}
		
		// Garbage man!
		delete objBody;
	},
	isRestrictedDate:function(currentDate)
	{
		if(this.calendarOptions.minDate)
		{
			if(currentDate.getTime() < this.calendarOptions.minDate.getTime())
			{
				return true;
			}
		} 
		
		if(this.calendarOptions.maxDate )
		{
			if(currentDate.getTime() > this.calendarOptions.maxDate.getTime())
			{
				return true;
			}
		}
                   
                   
		return false;
	},
    /**
     * Set options
     * @param (object) action
     */
    setOptions: function(optionsObject)
    {  
        if(optionsObject){
			/*Date comparisons may fail due to hour/minute/sec differences which we don't care about
			since we only want to compate days so we will specify precision of time to enhance date comparison*/
			 if(optionsObject['minDate'])
			 {
			 	optionsObject.minDate.setHours(0,0,0,0);
			 }
			 if(optionsObject['maxDate'])
             {
                optionsObject.maxDate.setHours(0,0,0,0);
             }
			 
           this.calendarOptions = optionsObject;
           this.refresh();
        }
        
    
    }
};

/**
 * Container for each cell (day empty or not) in the calendar table.  This object
 * makes is possible to associate different CSS classes or triggered event for
 * and individual day in the calendar.
 * 
 * @member Disney.WDPRO.UI.Widgets.Calendar
 * @requires Figment.DOM
 * @constructor
 */
Disney.WDPRO.UI.Widgets.Calendar.Cell = Figment.Class();
Disney.WDPRO.UI.Widgets.Calendar.Cell.prototype = {
	/**
	 * Constructor
	 * @param {Date} date
	 */
	initialize: function(date)
	{
		if( arguments.length === 0 )
		{
			date = null;
		}
		this.action = null;
		this.date = date;
		this.classes = [];
	},
	
	/**
	 * Changes the trigger event that will occur when the specific cell (day)
	 * is clicked.
	 * @param {Function} action
	 */
	setAction: function(action)
	{
		this.action = action;
	},
	
	/**
	 * Get the current date of this cell.
	 * @return {Date}
	 */
	getDate: function()
	{
		return this.date;
	},
	
	/**
	 * Add a CSS class name to this cell for rendering.
	 * @param {String} className
	 */
	addClassName: function(className)
	{
		this.classes.push(className);
	},
	
	/**
	 * Change the current CSS class name with another another one.
	 * @param {String} currentClassName
	 * @param {String} newClassName
	 */
	changeClassName: function(currentClassName,newClassName)
	{
		this.removeClassName(currentClassName);
		this.addClassName(newClassName);
	},
	
	/**
	 * Remove the specified CSS class name from this cell.
	 * @param {String} className
	 */
	removeClassName: function(className)
	{
		return this.classes.remove(className);
	}
	
};

// Run the create calendars on load of the document
Figment.EntryPoint.add( Disney.WDPRO.UI.Widgets.Calendar );
