/** @package eFocus js lib */

/**
 * efDatePicker Class - creates extended datepicker based on datepicker 1.16 by MonkeyPhysics.com
 * includes fix for error with Date() extension in MooTools more
 *
 * @author Klaas Dieleman <klaas[AT]efocus.nl>
 * @since 1.2, 09 feb, 2010
 * @copyright eFocus
 * @uses MooTools 1.2.3 Core <http://www.mootools.net>
 * @uses Datepicker 1.16 <http://www.monkeyphysics.com/mootools/script/2/datepicker>
 */

var efDatePicker = new Class({
	
	Implements: Options,
	Extends: DatePicker,
	
	options: { 
		disallowedDates: null, // { dates: '[array of date-strings]', format: '[date-string-interpretation-format]' }
		disallowedWeekdays: [] // [array of weedays(int)]
	},
	
	initialize: function(attachTo, options) {
		this.attachTo = attachTo;
		this.setOptions(options).attach();
		this.parent();
		this.formatDisallowedDates();
	},
	
	formatMinMaxDates: function() {
		
		if (this.options.minDate && this.options.minDate.inputFormat) { 
			 this.options.minDate = this.unformat(this.options.minDate.date, this.options.minDate.inputFormat);
		}
		if (this.options.maxDate && this.options.maxDate.inputFormat) {
			 this.options.maxDate = this.unformat(this.options.maxDate.date, this.options.maxDate.inputFormat);
			 this.options.maxDate.setHours(23);
			 this.options.maxDate.setMinutes(59);
			 this.options.maxDate.setSeconds(59);
		}
	},
	
	formatDisallowedDates: function() {
		if (this.options.disallowedDates && this.options.disallowedDates.inputFormat) {
			tempDisallowedDates = new Array;
			this.options.disallowedDates.dates.each(function(item, index) {
				tempDisallowedDates[index] = this.unformat(item, this.options.disallowedDates.inputFormat).toDateString();
			}.bind(this));
			this.options.disallowedDates = tempDisallowedDates;
		}
	},
	
	attach: function() {
		// toggle the datepicker through a separate element?
		if ($chk(this.options.toggleElements)) {
			var togglers = $$(this.options.toggleElements);
			document.addEvents({
				'keydown': function(e) {
					if (e.key == "tab") {
						this.close(null, true);
					}
				}.bind(this)
			});
		};
		
		// attach functionality to the inputs		
		$$(this.attachTo).each(function(item, index) {
			
			// never double attach
			if (item.retrieve('datepicker')) return;
			
			// determine starting value(s)
			if ($chk(item.get('value'))) {
				var init_clone_val = this.format(new Date(this.unformat(item.get('value'), this.options.inputOutputFormat)), this.options.format);
			} else if (!this.options.allowEmpty) {
				var init_clone_val = this.format(new Date(), this.options.format);
			} else {
				var init_clone_val = '';
			}
			
			// create clone
			var display = item.getStyle('display');
			var clone = item
			.setStyle('display', this.options.debug ? display : 'none')
			.store('datepicker', true) // to prevent double attachment...
			.clone()
			.store('datepicker', true) // ...even for the clone (!)
			.removeProperty('name')    // secure clean (form)submission
			.setStyle('display', display)
			.set('value', init_clone_val)
			.inject(item, 'after');
			
			// events
			if ($chk(this.options.toggleElements)) {
				togglers[index]
					.setStyle('cursor', 'pointer')
					.addEvents({
						'click': function(e) {
							this.onFocus(item, clone, index);
						}.bind(this)
					});
				clone.addEvents({
					'blur': function() {
						item.set('value', clone.get('value'));
					}
				});
			} else {
				clone.addEvents({
					'keydown': function(e) {
						if (this.options.allowEmpty && (e.key == "delete" || e.key == "backspace")) {
							item.set('value', '');
							e.target.set('value', '');
							this.close(null, true);
						} else if (e.key == "tab") {
							this.close(null, true);
						} else {
							e.stop();
						}
					}.bind(this),
					'focus': function(e) {
						this.onFocus(item, clone, index);
					}.bind(this)
				});
			}
		}.bind(this));
	},
	
	onFocus: function(original_input, visual_input, index) {
		var init_visual_date, d;
		if($chk(this.options.toggleElements)) {
			d = $$(this.options.toggleElements)[index].getCoordinates();
		} else {
			d = visual_input.getCoordinates();
		}
		
		if ($chk(original_input.get('value'))) {
			init_visual_date = this.unformat(original_input.get('value'), this.options.inputOutputFormat).valueOf();
		} else {
			init_visual_date = new Date();
			if ($chk(this.options.maxDate) && init_visual_date.valueOf() > this.options.maxDate.valueOf()) {
				init_visual_date = new Date(this.options.maxDate.valueOf());
			}
			if ($chk(this.options.minDate) && init_visual_date.valueOf() < this.options.minDate.valueOf()) {
				init_visual_date = new Date(this.options.minDate.valueOf());
			}
		}
		
		this.show({ left: d.left + this.options.positionOffset.x, top: d.top + d.height + this.options.positionOffset.y }, init_visual_date);
		this.input = original_input;
		this.visual = visual_input;
		this.options.onShow();
	},
	
	renderMonth: function() {
		var month = this.d.getMonth();
		
		this.picker.getElement('.titleText').set('text', this.options.months[month] + ' ' + this.d.getFullYear());
		
		this.d.setDate(1);
		while (this.d.getDay() != this.options.startDay) {
			this.d.setDate(this.d.getDate() - 1);
		}
		
		var container = new Element('div', { 'class': 'days' }).inject(this.newContents);
		var titles = new Element('div', { 'class': 'titles' }).inject(container);
		var d, i, classes, e, weekcontainer;

		for (d = this.options.startDay; d < (this.options.startDay + 7); d++) {
			var w = new Element('div', {'class': 'title day day' + (d % 7) });
			if (this.options.disallowedWeekdays.indexOf(d % 7) != -1) {
				w.addClass('unavailable');
			}
			w.set('text', this.options.days[(d % 7)].substring(0,this.options.dayShort));
			w.inject(titles);
		}
		
		var available = false;
		var t = this.today.toDateString();
		var currentChoice = this.dateFromObject(this.choice).toDateString();
		
		for (i = 0; i < 42; i++) {
			classes = [];
			classes.push('day');
			classes.push('day'+this.d.getDay());
			if (this.d.toDateString() == t) classes.push('today');
			if (this.d.toDateString() == currentChoice) classes.push('selected');
			if (this.d.getMonth() != month) classes.push('otherMonth');
			
			if (i % 7 == 0) {
				weekcontainer = new Element('div', { 'class': 'week week'+(Math.floor(i/7)) }).inject(container);
			}
			
			e = new Element('div', { 'class': classes.join(' ') }).set('text', this.d.getDate()).inject(weekcontainer);
			if (this.unavailable()) {
				e.addClass('unavailable');
			} else if (this.limited('date')) {
				e.addClass('unavailable');
				if (available) {
					this.limit.right = true;
				} else if (this.d.getMonth() == month) {
					this.limit.left = true;
				}
			} else {
				available = true;
				e.addEvent('click', function(e, d) {
					if (this.options.timePicker) {
						this.d.setDate(d.day);
						this.d.setMonth(d.month);
						this.mode = 'time';
						this.render('fade');
					} else {
						this.select(d);
					}
				}.bindWithEvent(this, { day: this.d.getDate(), month: this.d.getMonth(), year: this.d.getFullYear() }));
			}
			this.d.setDate(this.d.getDate() + 1);
		}
		if (!available) this.limit.right = true;
	},
	
	unavailable: function() {
		var da = $chk(this.options.disallowedDates);
		var dw = $chk(this.options.disallowedWeekdays);

		if (!da || this.options.disallowedWeekdays.length == 0) return false;
		
		return (da && this.options.disallowedDates.indexOf(this.d.toDateString()) != -1) || (dw && this.options.disallowedWeekdays.indexOf(this.d.getDay()) != -1);
	}
});