/**
 * DateInput
 * Mini calendar (YaCal) extended with open/close methods.
 * @author pop-wad [tw]
 */
var DateInput = Class.create(YaCal, {
	initialize: function($super, element, options){
		this.element = $(element); // text input element
		options = options || {};
		this.valueFormat = options.valueFormat || false;
		if(this.element.present() && Object.isUndefined(options.initialSelectedDate)){
			options.initialSelectedDate = YaCal.parseDate(this.element.value, this.valueFormat);
		}
		// construct wrapper and content html
		this.wrapper = new Element('div', {'class': 'dateinput', 'id': this.element.identify() + '-dateinput'});
		this.wrapper.update(options.contentSkin || "<div id='" + this.element.identify() + "-dateinput-container' class='container'></div>");
		element.insert({after: this.wrapper});
		
		var container = this.wrapper.down("div.container");
		if(!(Object.isElement(container))){
			throw (new Error("DateInput content skin does not have a div.container for the calendar table."));
		}
		// look for optional close link 
		var lnkClose = this.wrapper.down('a.close');
		if(Object.isElement(lnkClose)){
			lnkClose.observe('click', this.__lnkCloseClick.bindAsEventListener(this));
		}
		
		// pull effects out
		this._useEffects = options.useEffects || true;
		
		if (this._useEffects) {
			// pull effects out of the options and into private
			this._effects = Object.extend({
					openEffectType: Effect.SlideDown,
					openEffectOptions: {
						duration: 0.25,
						queue: {
							position: 'end',
							scope: 'dateinputscope'
						}
					},
					
					closeEffectType: Effect.SlideUp,
					closeEffectOptions: {
						duration: 0.25,
						queue: {
							position: 'end',
							scope: 'dateinputscope'
						}
					}
				}, options.effects || {});
			
			delete options.effects;
		}
		
		// initialize base YaCal
		$super(container, options);
		
		// event listeners		
		this.element.observe('change', this.__inputChange.bindAsEventListener(this)); 
		this.element.observe('focus', this.__inputFocus.bindAsEventListener(this));
		Event.observe(document.body, 'click', this.__bodyClick.bindAsEventListener(this));
		document.observe(this.containerID + ':day_selected', this.__daySelected.bindAsEventListener(this));
		// optional external trigger (calendar icon)
		this.trigger = (Object.isElement(options.trigger)) ? $(options.trigger) : false;
		if(this.trigger){
			this.trigger.observe('click', this.__triggerClick.bindAsEventListener(this));
		}

		this.wrapper.hide();
	},
	// Closes calendar if clicked outside.
	__bodyClick: function(e){
		var el = e.element();
		if(!el.descendantOf(this.container) && el !== this.element){
			this.close();
		}
	},
	// Closes calendar
	__lnkCloseClick: function(e){
		e.stop();
		this.close();
	},
	// Trigger (calendar icon)
	__triggerClick: function(e){
		e.stop();
		(this.wrapper.visible() == true) ? this.close() : this.open();
	},
	// Synchronizes the input value and yacal's selected date.
	__inputChange: function(e){
		if(this.element.present()){
			var dtSelected = this.getSelectedDate();
			var dtChanged = YaCal.parseDate(this.element.value, this.valueFormat);
			// basic validation
			if(dtChanged instanceof Date && !(isNaN(dtChanged.getTime()))){
				//console.log("valid date");
				if(dtSelected != dtChanged){
					this.setSelectedDate(dtChanged, true);	
				}
				this.close();
			}else{
				//console.warn('invalid date');
				if(dtSelected instanceof Date){
					//console.log("resetting input to the previously selected date")
					this.setValue(dtSelected);
				}
				this.element.fire(this.element.id + ':invalid_date', {"DateInput": this});
			}
		} else{
			this.reset();
		}
	},
	// Handles focus event on text input
	__inputFocus: function(e){
		this.open();
	},
	
	// Handles a date selected on Yacal, sets the text input's value
	__daySelected: function(ce){
		this.setValue(ce.memo.date);
		this.close();
	},
	// Opens the calendar
	open: function(){
		if (this.isOpen() == false && this._useEffects == true) {
			new this._effects.openEffectType(this.wrapper, this._effects.openEffectOptions);
		}else{
			this.wrapper.show();
		}
	},
	// Closes the calendar
	close: function(){
		if(this.isOpen() == true && this._useEffects == true){
			new this._effects.closeEffectType(this.wrapper, this._effects.closeEffectOptions);
		} else{
			this.wrapper.hide();
		}
	},
	// Sets the value of the text input.
	setValue: function(dt){
		var sFormat = this.valueFormat || 'm/d/Y'; 
		this.element.value = dt.toFormat(sFormat);
	},
	// Checks the visiblity of the wrapper.
	isOpen: function(){
		return this.wrapper.visible();
	}
});
