/*
Author:
	luistar15, <leo020588 [at] gmail.com>
License:
	MIT-style license.
 
Class
	datePicker
Arguments:
	input - DOM element
	options - see Options below
Options:
	startDate - [YYYY,MM(0-11),DD] or null | Default: (actual Date)
	position - object | Default: {x:'left',y:'bottom'}
	format - return date format | Default: '%d/%m/%Y'
		'%d	: day of the month(1-31)
		'%DD	: full textual representation of the week day (Lunes, Martes, ...)
		'%D	: short representation of the week day (Lun, Mar,...)
		'%m	: numeric representation of a month (1-12)
		'%MM	: full textual representation of the month (Enero, Febrero, ...)
		'%M	: short representation of month (Ene, Feb,...)
		'%y	: 2 digits representation of year (06,07,...)
		'%Y	: 4 digits representation of year (2006,20707,...)
	days - array with names of days | Default: spanish names
	months - array with names of months | Default: spanish names
	today - format to see today text | Default: false
	css_class - css class to assign to dataPicker box | Default: 'datePicker'
	offset - object with x and y distances from the input | Default: {x:0,y:2}
	marginYear - limits from show "years select" | Default: [-4,4]
	draggabñe - boolean | default: false
*/ 
var datePicker = new Class({
	options:{
		startDate: null,
		minDate: null,
		maxDate: null,
		position: {x:'left',y:'bottom'},
		format: '%d/%m/%Y',
		days: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'],
		months: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
		today: false,
		css_class: 'datePicker',
		controller:'click',
		offset: {x:0,y:0},
		marginYear: [-4,4],
		draggable: false,
		onSelect: Class.empty
	},

	initialize:function(input,options){
		this.setOptions(options);
		this.current = new Date();
		if(this.options.startDate) this.current.setFullYear(this.options.startDate[0],this.options.startDate[1],this.options.startDate[2]);
		this.lastDates = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
		this.dp = new Element('div',{'class':this.options.css_class+' hidden'}).inject($E('body'));
		if(this.options.draggable) this.dp.makeDraggable({handle:new Element('div',{'class':'handle'}).inject(this.dp)});
		this.month = new Element('span',{'class':'month','events':{'click':this.displayMonths.bind(this)}}).setHTML(this.options.months[this.current.getMonth()]).inject(this.dp);
		this.year = new Element('span',{'class':'year','events':{'click':this.displayYears.bind(this)}}).setHTML(this.current.getFullYear()).inject(this.dp);
		new Element('span',{'class':'close','events':{'click':this.hide.bind(this)}}).setHTML('X').inject(this.dp);
		var dayTitles = ''; for(var i=0;i<this.options.days.length;i++) dayTitles+='<b>'+this.options.days[i].substr(0,1)+'</b>';
		new Element('div').setHTML(dayTitles).inject(this.dp);
		this.daysBox = new Element('div').inject(this.dp);
		if(this.options.today){
			this.today = new Date();
			var todayText = this.parseDate(this.today,this.options.today);
			new Element('a',{'href':'//'+todayText,'class':'today','events':{'click':this.setToday.bind(this)}}).setHTML(todayText).inject(this.dp);
		}
		this.input = input.addEvents({
			'click':this.show.bind(this),
			'focus':this.show.bind(this),
			'keydown':function(e){
					if(this.dp.hasClass('hidden')) return;
					var event = new Event(e);
					if(event.key=='tab' || event.key=='esc') this.hide()
			}.bind(this)
		});
		this.build();
	},
	
	build:function(){
		this.lastDates[1] = this.current.getFullYear()%4>0?28:29;
		if(this.current.getDate()>this.lastDates[this.current.getMonth()]) this.current.setDate(this.lastDates[this.current.getMonth()]);
		this.daysBox.innerHTML='';
		var currentMonth = this.current.getMonth();
		var startDay = this.current.getDay()-(this.current.getDate()%7); startDay+=startDay<0?8:1;
		var from = startDay<7?0-startDay:0;
		var to = this.lastDates[currentMonth]+startDay; if(to%7>0) to=to+(7-to%7); to-=startDay;
		var previousMonth = currentMonth==0?11:currentMonth-1;
		var previousStartDate = this.lastDates[previousMonth]-startDay+1;
		var firstNextDate = 1;
		for(var i=from;i<to;i++){
			var day = i+1;
			var css_class = day==this.current.getDate()?'selected':'';
			if(
				(this.options.minDate && this.current.getFullYear()==this.options.minDate[0] && this.current.getMonth()==this.options.minDate[1] && day<this.options.minDate[2]) ||
				(this.options.maxDate && this.current.getFullYear()==this.options.maxDate[0] && this.current.getMonth()==this.options.maxDate[1] && day>this.options.maxDate[2])
			) css_class += ' disabled';
			if(i<0) new Element('span').setHTML(previousStartDate++).inject(this.daysBox);
			else if(i>this.lastDates[currentMonth]-1) new Element('span').setHTML(firstNextDate++).inject(this.daysBox);
			else new Element('a',{'href':'//day:'+day,'class':css_class,'events':{'click':this.setDate.bind(this)}}).setHTML(day).inject(this.daysBox);
		}
	},

	displayMonths:function(){
		this.selectMonth = new Element('p',{'class':'selectMonth','events':{'mouseleave':function(){this.remove()}}}).inject(this.dp);
		var handle = $E('.handle',this.dp);
		if(handle) this.selectMonth.setStyle('top',(handle.offsetHeight+handle.getStyle('margin-bottom').toInt())+'px');
		for(var i=0;i<12;i++){
			var css_class = i==this.current.getMonth()?'selected':'';
			if(
				(this.options.minDate && this.current.getFullYear()==this.options.minDate[0] && i<this.options.minDate[1]) ||
				(this.options.maxDate && this.current.getFullYear()==this.options.maxDate[0] && i>this.options.maxDate[1])
			) css_class += ' disabled';
			new Element('a',{'href':'//'+this.options.months[i],'value':i,'class':css_class,'events':{'click':this.setMonth.bind(this)}}).setHTML(this.options.months[i]).inject(this.selectMonth);
		}
	},

	displayYears:function(){
		this.selectYear = new Element('p',{'class':'selectYear','events':{'mouseleave':function(){this.remove()}}}).inject(this.dp);
		var handle = $E('.handle',this.dp);
		if(handle) this.selectYear.setStyle('top',(handle.offsetHeight+handle.getStyle('margin-bottom').toInt())+'px');

		var from = this.current.getFullYear()+this.options.marginYear[0];
		if(this.options.minDate && from<this.options.minDate[0]) from=this.options.minDate[0];

		var to = this.current.getFullYear()+this.options.marginYear[1];
		if(this.options.maxDate && to>this.options.maxDate[0]) to=this.options.maxDate[0];

		for(var i=from;i<=to;i++) new Element('a',{'href':'//year:'+i,'class':i==this.current.getFullYear()?'selected':'','events':{'click':this.setYear.bind(this)}}).setHTML(i).inject(this.selectYear);
		new Element('a',{'href':'//increase-year','class':'more','events':{'click':this.decreaseYear.bind(this)}}).setHTML('-').injectTop(this.selectYear);
		new Element('a',{'href':'//decrease-year','class':'more','events':{'click':this.increaseYear.bind(this)}}).setHTML('+').inject(this.selectYear);
	},
	
	decreaseYear:function(event){
		new Event(event).stop();
		var el = event.target || event.srcElement;
		var year = el.getNext().innerHTML.toInt()-1;
		if(this.options.minDate && year<this.options.minDate[0]) return false;
		el.getParent().getLast().getPrevious().remove();
		new Element('a',{'href':'//year:'+year,'class':year==this.current.getFullYear()?'selected':'','events':{'click':this.setYear.bind(this)}}).setHTML(year).injectAfter(el);
	},

	increaseYear:function(event){
		new Event(event).stop();
		var el = event.target || event.srcElement;
		var year = el.getPrevious().innerHTML.toInt()+1;
		if(this.options.maxDate && year>this.options.maxDate[0]) return false;
		el.getParent().getFirst().getNext().remove();
		new Element('a',{'href':'//year:'+year,'class':year==this.current.getFullYear()?'selected':'','events':{'click':this.setYear.bind(this)}}).setHTML(year).injectBefore(el);
	},

	setYear:function(event){
		new Event(event).stop();
		var el = event.target || event.srcElement;
		if(el.innerHTML.toInt()==this.current.getFullYear()) return;
		var year = el.innerHTML.toInt();
		this.year.setHTML(year);
		this.current.setFullYear(year);
		if(this.options.minDate && year==this.options.minDate[0] && this.current.getMonth()<this.options.minDate[1]){
			this.current.setMonth(this.options.minDate[1]);
			this.month.setHTML(this.options.months[this.options.minDate[1]]);
		}
		if(this.options.maxDate && year==this.options.maxDate[0] && this.current.getMonth()>this.options.maxDate[1]){
			this.current.setMonth(this.options.maxDate[1]);
			this.month.setHTML(this.options.months[this.options.maxDate[1]]);
		}
		this.selectYear.remove();
		this.build();
	},
	
	setMonth:function(event){
		new Event(event).stop();
		var el = event.target || event.srcElement;
		if(el.hasClass('disabled') || el.getProperty('value').toInt()==this.current.getMonth()) return;
		this.month.setHTML(el.innerHTML);
		this.current.setMonth(el.getProperty('value').toInt());
		this.selectMonth.remove();
		this.build();
	},

	setDate:function(event){
		new Event(event).stop();
		var el = event.target || event.srcElement;
		if(el.hasClass('disabled')) return;
		this.hide();
		this.current.setDate(el.innerHTML.toInt());
		this.input.setProperty('value',this.parseDate(this.current,this.options.format));
		var prevSelected = $E('a.selected',this.dp); if(prevSelected) prevSelected.removeClass('selected');
		el.addClass('selected');
		if(!window.ie) this.input.focus();
		this.hide();
		this.fireEvent('onSelect', [this.input]);
	},
	
	setToday:function(event){
		this.hide();
		new Event(event).stop();
		var year = this.today.getFullYear();
		var month = this.today.getMonth();
		var date = this.today.getDate();
		this.current.setFullYear(year,month,date);
		this.input.setProperty('value',this.parseDate(this.current,this.options.format));
		this.year.setHTML(year);
		this.month.setHTML(this.options.months[month]);
		$ES('div a',this.dp).each(function(el){if(el.hasClass('selected')) el.removeProperty('class'); else if(el.innerHTML==date) el.addClass('selected')});
		if(!window.ie) this.input.focus();
		this.hide();
		this.fireEvent('onSelect', [this.input]);
	},

	show:function(){
		if(this.input.getProperty('prevent')) return;
		var pos = this.input.getCoordinates();
		this.dp.setStyles('top:'+(eval('pos.'+this.options.position.y).toInt()+this.options.offset.y)+'px;left:'+(eval('pos.'+this.options.position.x).toInt()+this.options.offset.x)+'px').removeClass('hidden');
	},
	
	hide:function(){
		//this.dp.addClass('hidden');
		this.dp.setOpacity(0);
	},
	
	parseDate:function(dateObject,format){
		return format.
		replace('%d',(dateObject.getDate()<10?'0'+dateObject.getDate():dateObject.getDate())).
		replace('%DD',this.options.days[dateObject.getDay()]).
		replace('%D',this.options.days[dateObject.getDay()].substr(0,3)).
		replace('%m',(dateObject.getMonth()+1<10?'0'+(dateObject.getMonth()+1):dateObject.getMonth()+1)).
		replace('%MM',this.options.months[dateObject.getMonth()]).
		replace('%M',this.options.months[dateObject.getMonth()].substr(0,3)).
		replace('%y',('s'+dateObject.getFullYear()).substr(3)).
		replace('%Y',dateObject.getFullYear())
	}
	
});

datePicker.implement(new Options, new Events);