/***************************************************************************
 * mootools-moocalendar.input-2.0.js
 * ---------------
 *   author		-> Andrew Taylor
 *   started	-> Monday, Oct 25th, 2010
 *   modified	-> Monday, Oct 25th, 2010
 *   copyright	-> 
 *   email     	-> andrew@brightlabs.com.au
 *   version    -> 2.0.0
 *
 * file description
 * ------------------
 * Extends mooCalendar2 to provide an input calendar
 * 
 * Developed for Dr On Call
 * 
 * Based on Mootools Calendar Events 2.0 by Chris Colbourne
 *
 * provides
 * ------------------
 * mooCalendar2.Input
 * 
 * 
 * requires
 * ------------------
 * mooCalendar2
 * core:1.2.4
 * more:1.2.4.4
 * functions
 * 
 * 
 * change log
 * ------------------
 * 2.0			Initial development
 *
 ***************************************************************************/


mooCalendar2.Input = new Class({

	Extends: mooCalendar2,
	
	options: {	'dayLength': 'dayLengthSingle',
				'dateFormat': 'd/m/Y',
				'dateSplitter': '/',
				'calElement': 'mooCalendarInput2',
				'targetClass': 'input.mooCalendar',
				'onDayClick': function(cell, date) { this.fillDate(cell,date); }
	},
	
					/*--------------------------------------------------------o
	----------------\                     Member Variables                    |
		variables    \-------------------------------------------------------*/
					
	triggerElement: null,
	created: false,
	active: false,
	FX: null,
	docBody: null,
	hasFocus: false,
	hidden: true,
	timeoutId: null,
	activeDate: null,
	
	
					/*--------------------------------------------------------o
	----------------\                    Internal Functions                   |
		 internal    \-------------------------------------------------------*/
		
	initialize: function(options) {
		this.setOptions(options);
				
		var cal = new Element('div', {id: this.options.calElement});
		cal.setStyle('opacity', 0);
		cal.setStyle('display', 'none');
		
		var tmp = $$('body');
		this.docBody = tmp[0]
		this.docBody.adopt(cal);
		
		this.FX = new Fx.Morph(cal, {	'duration': 600, 
										'wait': false, 
										'transition': Fx.Transitions.Quad.easeOut, 
										'onComplete': 	function() { 
															if ( $(this.options.calElement).getStyle('opacity') == 0 ) {
																$(this.options.calElement).setStyle('display', 'none')
															}
															if ( this.timeoutId ) {
																window.clearTimeout(this.timeoutId);
																this.timeoutId = null;
															}
														}.bind(this)
										});
		
		
		
		// Find each mooCalendar input field
		if ( $$(this.options.targetClass) && $$(this.options.targetClass).length ) {
			$$(this.options.targetClass).each(function(elem, idx) {
				elem.addEvent('click', function() {
					this.FX.cancel();
					this.toggleCalendar(elem, this.parent);
				}.bind(this));
				elem.readOnly = 'readonly';
			}.bind(this));
		}
		
		this.parent($(this.options.calElement), options);
			
		// Add the click-away close feature
		$(document.body).addEvent('click',function(e) {
			if( !(this.hidden || $(e.target).getParents().contains($(this.options.calElement)) || e.target == this.triggerElement) ) {
				this.hide();
				this.triggerElement = null;
			}
		}.bind(this));
		
	},

					/*--------------------------------------------------------o
	----------------\                   Setup Functions                       |
		  setup      \-------------------------------------------------------*/

	
	createDateDropdowns: function () { 

		this.parent();
		
		var calDropElements = $$('#' + this.options.calElement + ' .calDropdownContainer');
		
		if ( calDropElements.length ) {
			calDropElements.each(function(elem, idx) {
				if ( !elem.closeAttached ) {
					
					var closeLink = new Element('a', {'text': 'Close', 'class': 'calendarClose'});
					closeLink.addEvent('click', function(e) {
						e.stop();
						this.hide();
						this.triggerElement = null;
					}.bind(this));
					elem.adopt(closeLink);
					
				}
				elem.closeAttached = true;
			}.bind(this));
		}
		
	},
	
	createDayElement: function (dayNum, day) { 
		
		var li = this.parent(dayNum, day);
		
		// Active Class
		if ( 	this.activeDate &&
				this.activeDate.get('year') == this.curDate.get('year') && 
				this.activeDate.get('month') == this.curDate.get('month') ) {
		
			var classes = li.className.split(" ");
			
			for (var i=0; i<classes.length; i++) {
				if (classes[i] == 'calDate' + this.activeDate.get('date')) {
					li.addClass('calDayActive');
					break;
				}
			}
		}
		
		return li;
	},
	
	toggleCalendar: function(triggerElement) {
		
		this.activeDate = null;
		
		if ( !triggerElement ) {
			alert('No trigger element specified, please check your code.');
			return false;
		}
		
		if ( triggerElement != this.triggerElement ) {
			this.hidden = false;
		
			this.triggerElement = triggerElement;
			this.curDate = new Date();
			
			if ( this.triggerElement.value ) {
				
				// Get the date parts of the input field based on the format that is given in the options
				var dateSplit = this.triggerElement.value.split(this.options.dateSplitter);
				var formatSplit = this.options.dateFormat.split(this.options.dateSplitter);
				
				var d_position = null;
				var m_position = null;
				var y_position = null;
				
				// Loop over the supplied format to find each date part
				for (var i=0; i<formatSplit.length; i++) {
					if ( formatSplit[i] == 'y' || formatSplit[i] == 'Y' ) {
						y_position = i;
					} else if ( formatSplit[i] == 'm' || formatSplit[i] == 'n' ) {
						m_position = i;
					} else if ( formatSplit[i] == 'd' || formatSplit[i] == 'j' ) {
						d_position = i;
					}
				}
				
				// If we have a complete date provided, set it as both the current and active dates
				if ( 	dateSplit[d_position] &&
						dateSplit[m_position] &&
						dateSplit[y_position] 
				) {
					var d = parseInt(dateSplit[d_position], 10);
					var m = parseInt(dateSplit[m_position], 10);
					var y = parseInt(dateSplit[y_position], 10);
					this.activeDate = new Date(parseInt(y, 10), parseInt(m, 10)-1, parseInt(d, 10));
					this.curDate = new Date(parseInt(y, 10), parseInt(m, 10)-1, parseInt(d, 10));
				}
			}
			
			this.display();
			
		} else {
			this.hide();
			this.triggerElement = null;
		}
	},
	
	fillDate: function(cell, date) {
		
		// Insert the selected date into the selected input field
		if ( this.triggerElement ) {
			var newDate = this.options.dateFormat;
			newDate = newDate.replace(/d/, ((date.get('date') < 10) ? '0' : '') + date.get('date'));
			newDate = newDate.replace(/j/, date.get('date'));
			newDate = newDate.replace(/m/, ((date.get('month')+1 < 10) ? '0' : '') + (date.get('month')+1));
			newDate = newDate.replace(/n/, date.get('month')+1);
			newDate = newDate.replace(/y/, (date.get('year')+'').substr(2,2));
			newDate = newDate.replace(/Y/, date.get('year'));
			this.triggerElement.value = newDate;
		}
		
		this.hide();
		
		// Fire the change event if it has been assigned to the target element
		if ( this.triggerElement && this.triggerElement.change ) {
			this.triggerElement.change();
		}
		this.triggerElement = null;
	},
	
	display: function() {
		
		if ( !this.triggerElement ) {
			return false;
		}
		
		this.create();
		this.onCreate();
		
		ePos = this.triggerElement.getPosition();
		eSize = this.triggerElement.getSize();
		wSize = this.docBody.getSize();
		cSize = $(this.options.calElement).getSize();
		
		$(this.options.calElement).setStyle('position', 'absolute');
		$(this.options.calElement).setStyle('opacity', '1');
		$(this.options.calElement).setStyle('display', '');
		$(this.options.calElement).setStyle('left', ePos.x + 'px');
		
		// Position it!
		if ( ePos.y + eSize.y + cSize.y + this.itemBuffer > wSize.y ) {
			$(this.options.calElement).setStyle('top', (ePos.y - cSize.y) + 'px');
		} else {
			$(this.options.calElement).setStyle('top', ePos.y + eSize.y + 'px');
		}
	},
	
	
	hide: function() {
		if ( this.timeoutId ) {
			window.clearTimeout(this.timeoutId);
			this.timeoutId = null;
		}
		
		this.hidden = true;
		this.FX.cancel();
		this.FX.start({ 'opacity': [$(this.options.calElement).getStyle('opacity'), 0]	});
	}
	
});

