/**
 * Events:
 * 	- onSelect ( parameter: date selected )
 */
var NetronautUI_Widgets_Calendar = new Class
({
	Extends: NetronautUI_Widget,
	
	options: {
		date: null,
		viewDate: null,
		limit: {from:null, to:null},
		days: null,
		months: null,
		markCurrent: true
	},
	
	monthItems: [],
	
	initialize: function ( el, options ) {
		options = options || {};
		options.date = options.date || new Date();
		options.days = options.days || Locale.get('Date.days');
		options.months = options.months || Locale.get('Date.months');
		
		this.parent(el, options);
		
		this.dom.previous.addEvent('click', this.viewMonthRelative.pass(-1, this));
		this.dom.next.addEvent('click', this.viewMonthRelative.pass(1, this));
	},
	
	render: function () {
		this.dom.el.addClass('netronautui-calendar');
		this.dom.head = new Element('div', {'class':'netronautui-calendar-header'}).adopt(
			this.dom.previous = new Element('button', {'type':'button', 'class':'button netronautui-calendar-previous'}),
			this.dom.next = new Element('button', {'type':'button', 'class':'netronautui-calendar-next'}),
			this.dom.caption = new Element('div', {'class':'netronautui-calendar-caption'})
		).inject(this.dom.el);
		var thead = new Element('thead').adopt(tr=new Element('tr'));
		Array.each(this.options.days, function(day){
			new Element('td', {text:day.substr(0,1), href:'javascript:void(0);', title:day}).inject(tr);
		});
		this.dom.calendar = new Element('table', {'class':'netronautui-calendar-calendar'}).inject(this.dom.el).adopt(thead,new Element('tbody'));
		return this;
	},
	
	/**
	 * Update the display, showing the current viewDate.
	 * 
	 * viewDate may be another date as the current (selected) date.
	 * 
	 * @param Date date Optional
	 */
	viewMonth: function ( date ) {
		var date = (date || this.options.viewDate || this.options.date || new Date()).clone().clearTime();
		this.options.viewDate = date;
		this.dom.caption.set('text', this.options.months[date.get('month')] + ' ' + date.get('year'));
		
		// clone a date to work on
		var d = date.clone().set('date', 1);
		var month_start_day = d.get('day');
		var days_to_display = Math.ceil((month_start_day+d.get('lastdayofmonth'))/7)*7;
		d.decrement('day', month_start_day);
		
		// enable/disable month change buttons
		if(this.getLimit().from && d.clone().decrement('day', 1).diff(this.getLimit().from)>0) {
			this.dom.previous.addClass('disabled').addClass('netronautui-calendar-previous-disabled').set('disabled', 'disabled');
		} else {
			this.dom.previous.removeClass('disabled').removeClass('netronautui-calendar-previous-disabled').erase('disabled');
		}
		if(this.getLimit().to && d.clone().increment('day', days_to_display).diff(this.getLimit().to)<0) {
			this.dom.next.addClass('disabled').addClass('netronautui-calendar-next-disabled').set('disabled', 'disabled');
		} else {
			this.dom.next.removeClass('disabled').removeClass('netronautui-calendar-next-disabled').erase('disabled');
		}
		
		// draw month view
		var row = new Element('tr').inject(this.dom.calendar.getElement('tbody').empty());
		this.monthItems = Array();
		for(var i=0; i<days_to_display; i++) {
			var item;
			var cell = new Element('td').inject(row).adopt(item = new Element('button', {
				'type':'button',
				'class':'button',
				text:d.get('date'),
				events:{'click':function(event){
					this.bind.fireEvent('select', [this.date, event]);
				}}
			}));
			item.bind = this;
			item.date = d.clone();
			this.monthItems.push(item);
			if(this.options.markCurrent && d.diff(this.options.date.clone().clearTime())==0) {
				cell.addClass('netronautui-calendar-current-date');
			}
			if(d.get('month')==date.get('month')) {
				cell.addClass('netronautui-calendar-current-month');
			}
			if((this.options.limit.from && d.diff(this.options.limit.from)>0)
			|| (this.options.limit.to && d.diff(this.options.limit.to)<0)) {
				item.set('disabled', 'disabled').addClass('disabled');
			}
			d.increment('day', 1);
			if(d.get('day')==0) {
				row = new Element('tr').inject(this.dom.calendar.getElement('tbody'));
			}
		}
		this.fireEvent('viewMonth', this.options.viewDate);
		return this;
	},
	
	/**
	 * Return a list of all calendar day items
	 * in the current month view.
	 * 
	 * @return Array
	 */
	getMonthItems: function () {
		return this.monthItems;
	},
	
	/**
	 * View a month relative to the current view data / date.
	 * 
	 * @param Number to_month
	 */
	viewMonthRelative: function ( to_month ) {
		var d = this.options.viewDate || this.options.date.clone();
		this.viewMonth(to_month<0 ?d.decrement('month', Math.abs(to_month)) :d.increment('month', Math.abs(to_month)));
		this.fireEvent('changeMonth');
		return this;
	},
	
	/**
	 * Set the current date.
	 * 
	 * @param Date date
	 */
	setDate: function ( date ) {
		this.options.date = date.clearTime();
		return this;
	},
	
	/**
	 * Get the current date.
	 * 
	 * @return Date
	 */
	getDate: function () {
		return this.options.date;
	},
	
	/**
	 * Set the current date and update the display.
	 * 
	 * @param Date date
	 */
	gotoDate: function ( date ) {
		this.setDate(date);
		this.viewMonth(date);
		return this;
	},
	
	/**
	 * Set date constraints.
	 * 
	 * @param Object limit In the form {from:Date, to:Date}
	 */
	setLimit: function ( limit ) {
		this.options.limit = {
			from:limit.from ?limit.from.clearTime() :null,
			to:limit.to ?limit.to.clearTime() :null
		};
		return this;
	},
	
	/**
	 * Get the date constraints.
	 * 
	 * @return Object 
	 */
	getLimit: function () {
		return this.options.limit;
	}
});
