var datePicker = new Class({

	Implements: [Events, Options],

	options:{
		//onSelect: $empty,
		startDate: false,
		minDate: false,
		maxDate: false,
		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,
		cssClass: 'datePicker',
		offset: {x:0,y:0}
	},

	initialize:function(input,options){
		this.setOptions(options);
		this.lastDates = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
		this.current = new Date();
		this.selected = {d:false,m:false,y:false};

		if(this.options.startDate){
			this.current.setFullYear(this.options.startDate[0],this.options.startDate[1],this.options.startDate[2]);
			this.updateSelected();
		}

		this.dp = new Element('div',{'class':this.options.cssClass+' hidden'}).inject(document.body);
		this.month = new Element('span',{'class':'month'}).addEvent('click',this.displayMonths.bind(this)).setHTML(this.options.months[this.current.getMonth()]).inject(this.dp);
		this.year = new Element('span',{'class':'year'}).addEvent('click',this.displayYears.bind(this)).setHTML(this.current.getFullYear()).inject(this.dp);
		new Element('span',{'class':'close'}).addEvent('click',this.hide.bind(this)).setHTML('X').inject(this.dp);

		var dayTitles = new Element('div').inject(this.dp);
		for(var i=0;i<7;i++){
			dayTitles.innerHTML+='<b>'+this.options.days[i].substr(0,1)+'</b>';
		}

		this.daysBox = new Element('div').inject(this.dp);

		if(this.options.today){
			this.today = new Date();
			var todayTime = this.today.getTime();
			if(this.options.minDate){
				var minDate = new Date(this.options.minDate[0],this.options.minDate[1],this.options.minDate[2]).getTime()-86400000;
			}
			if(this.options.maxDate){
				var maxDate = new Date(this.options.maxDate[0],this.options.maxDate[1],this.options.maxDate[2]).getTime()+86400000;
			}
			if(
				(!minDate || minDate<=todayTime) &&
				(!maxDate || maxDate>=todayTime)
			){
				new Element('span',{'class':'today','events':{'click':this.setToday.bind(this)}}).setHTML(this.parseDate(this.today,this.options.today)).inject(this.dp);
			}
		}

		this.input = input.addEvents({
			'mouseup': this.show.bind(this),
			'focus': this.show.bind(this),
			'keydown': function(e){
				if(!this.dp.hasClass('hidden')){
					var ev = new Event(e);
					if(['tab','esc','delete'].contains(ev.key)){
						if(ev.key=='delete'){
							this.input.value='';
							this.fireEvent('onSelect',[false,false,false]);
						}
						this.hide();
					}
				}
			}.bind(this)
		});
		
		this.showed = false;
		this.yTimer;
	},
	
	displayDays:function(){
		this.lastDates[1] = this.current.getFullYear()%4>0?28:29;
		this.daysBox.innerHTML='';

		var currentMonth = this.current.getMonth();

		if(this.current.getDate()>this.lastDates[currentMonth]){
			this.current.setDate(this.lastDates[currentMonth]);
		}
	
		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 cssClass = day==this.selected.d && currentMonth==this.selected.m && this.current.getFullYear()==this.selected.y ? 'selected' : '';
			if((this.options.minDate && this.current.getFullYear()==this.options.minDate[0] && currentMonth==this.options.minDate[1] && day<this.options.minDate[2]) ||(this.options.maxDate && this.current.getFullYear()==this.options.maxDate[0] && currentMonth==this.options.maxDate[1] && day>this.options.maxDate[2])){cssClass += ' disabled';}
			if(i<0){
				new Element('i').setHTML(previousStartDate++).inject(this.daysBox);
			}else if(i>this.lastDates[currentMonth]-1){
				new Element('i').setHTML(firstNextDate++).inject(this.daysBox);
			}else{
				new Element('span',{'class':cssClass}).addEvent('click',this.setDate.bind(this)).setHTML(day).inject(this.daysBox);
			}
		}
	},

	displayMonths:function(){
		var months = [];
		for(var i=0;i<12;i++){
			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])){
				months.push(i);
			}
		}
		if(months.length>1){
			this.selectMonth = new Element('p',{'class':'selectMonth'}).addEvent('mouseleave',function(){this.remove()}).inject(this.dp);
			for(var j=0;j<months.length;j++){
				new Element('span',{'value':months[j],'class':months[j]==this.current.getMonth()?'selected':''}).addEvent('click',this.setMonth.bind(this)).setHTML(this.options.months[months[j]]).inject(this.selectMonth);
			}
		}
	},

	displayYears:function(){
		var from = this.current.getFullYear()-3;
		if(this.options.minDate && from<this.options.minDate[0]) from=this.options.minDate[0];
		var to = this.current.getFullYear()+3;
		if(this.options.maxDate && to>this.options.maxDate[0]) to=this.options.maxDate[0];
		if(to>from){
			this.selectYear = new Element('p',{'class':'selectYear'}).addEvent('mouseleave',function(){this.remove();$clear(this.yTimer);}).inject(this.dp);
			for(var i=from;i<=to;i++){
				new Element('span',{'class':i==this.current.getFullYear()?'selected':''}).addEvent('click',this.setYear.bind(this)).setHTML(i).inject(this.selectYear);
			}
			new Element('span',{'class':'more'}).addEvents({
				'mouseover': function(e){this.yTimer = this.decreaseYear.periodical(100,this,[new Event(e).target]);}.bind(this),
				'mouseout': function(){$clear(this.yTimer);}.bind(this)
			}).setHTML('-').injectTop(this.selectYear);
			new Element('span',{'class':'more'}).addEvents({
				'mouseover': function(e){this.yTimer = this.increaseYear.periodical(100,this,[new Event(e).target]);}.bind(this),
				'mouseout': function(){$clear(this.yTimer);}.bind(this)
			}).setHTML('+').inject(this.selectYear);
			(function(){$clear(this.yTimer);}.bind(this)).delay(100);
		}
	},

	setDate:function(e){
		var el = new Event(e).target;
		if(!el.hasClass('disabled')){
			this.current.setDate(el.innerHTML.toInt());
			this.updateSelected();
			this.input.setProperty('value',this.parseDate(this.current,this.options.format));
			if(Browser.Engine.name!='trident'){this.input.focus();}
			this.hide();
			this.fireEvent('onSelect',[this.selected.y,this.selected.m,this.selected.d]);
		}
	},

	setMonth:function(e){
		var el = new Event(e).stop().target;
		if(!el.hasClass('selected')){
			this.month.setHTML(el.innerHTML);
			this.current.setDate(1);
			this.current.setMonth(el.getProperty('value').toInt());
			this.displayDays();
		}
		this.selectMonth.remove();
	},

	setYear:function(e){
		var el = new Event(e).stop().target;
		if(!el.hasClass('selected')){
			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.displayDays();
		}
		$clear(this.yTimer);
	},

	setToday:function(){
		this.current = this.today;
		this.updateSelected();
		this.input.setProperty('value',this.parseDate(this.current,this.options.format));
		this.year.setHTML(this.selected.y);
		this.month.setHTML(this.options.months[this.selected.m]);
		if(Browser.Engine.name!='trident') this.input.focus();
		this.hide();
		this.fireEvent('onSelect',[this.selected.y,this.selected.m,this.selected.d]);
	},

	setFullDate:function(year,month,date){
		this.current.setFullYear(year,month,date);
		this.updateSelected();
		this.input.setProperty('value',this.parseDate(this.current,this.options.format));
		this.year.setHTML(this.selected.y);
		this.month.setHTML(this.options.months[this.selected.m]);
		this.hide();
	},

	decreaseYear:function(el){
		var year = el.getNext().innerHTML.toInt()-1;
		if(!this.options.minDate || year>=this.options.minDate[0]){
			el.getParent().getLast().getPrevious().remove();
			new Element('span',{'class':year==this.current.getFullYear()?'selected':''}).addEvent('click',this.setYear.bind(this)).setHTML(year).injectAfter(el);
		}else{
			$clear(this.yTimer);
		}
	},

	increaseYear:function(el){
		var year = el.getPrevious().innerHTML.toInt()+1;
		if(!this.options.maxDate || year<=this.options.maxDate[0]){
			el.getParent().getFirst().getNext().remove();
			new Element('span',{'class':year==this.current.getFullYear()?'selected':''}).addEvent('click',this.setYear.bind(this)).setHTML(year).injectBefore(el);
		}else{
			$clear(this.yTimer);
		}
	},

	updateSelected: function(){
		this.selected = {
			d: this.current.getDate(),
			m: this.current.getMonth(),
			y: this.current.getFullYear()
		};
	},
	
	show:function(){
		if(!this.showed && !this.input.getProperty('prevent')){
			this.showed = true;
			this.displayDays();
			var pos = this.input.getCoordinates();
			this.dp.setStyles({
				top:(pos[this.options.position.y].toInt()+this.options.offset.y)+'px',
				left:(pos[this.options.position.x].toInt()+this.options.offset.x)+'px'
			}).removeClass('hidden');
		}
	},

	hide:function(){
		this.showed = false;
		this.daysBox.innerHTML='';
		this.dp.addClass('hidden');
	},
	
	parseDate:function(obj,format){
		return format.
		replace('%d',(obj.getDate()<10?'0'+obj.getDate():obj.getDate())).
		replace('%DD',this.options.days[obj.getDay()]).
		replace('%D',this.options.days[obj.getDay()].substr(0,3)).
		replace('%m',(obj.getMonth()+1<10?'0'+(obj.getMonth()+1):obj.getMonth()+1)).
		replace('%MM',this.options.months[obj.getMonth()]).
		replace('%M',this.options.months[obj.getMonth()].substr(0,3)).
		replace('%y',(obj.getFullYear()+'').substr(2)).
		replace('%Y',obj.getFullYear());
	}
	
});

