/*
Author:
	luistar15, <leo020588 [at] gmail.com>
License:
	MIT License
 
Class
	datePicker (v0.8)

Arguments:
	el: dom element
	Parameters - see Parameters below

Parameters:
	format: string | return date format | default: '%d/%m/%Y',
	position: object | datePicker position respect el | default: {x:'left',y:'bottom'},
	offset: object | datePicker position offsets | default: {x:0,y:5},
	from: array [yyyy,m(0-11),a] | initial date of the available range | dafault: false
	to:  array [yyyy,m(0-11),a] | final date of the available range | dafault: false
	initial: array [yyyy,m(0-11),a] | initial date | dafault: today
	setInitial: boolean | update "el" on create instance | default: false
	updateElement: boolean | update "el" on select date | default: true
	draggable: boolean | draggable instance | default: false,
	firstday: int | initial day of the week | default: 0=Sunday
	klass: string | CSS class of the instance | default: 'datePicker'
	days: array | days name | default: spanish names
	months: array | months name | default: spanish names
	onShow: event function
	onHide: event function
	onUpdate: event function

Requires:
	mootools 1.2 core
	<Drag.Move> ->  mootools 1.2 more for "draggable" option
*/

var datePicker = new Class({

	Implements: [Options,Events],

	options: {
		format: '%d.%m.%Y',
		position: {x:'left',y:'bottom'},
		offset: {x:0,y:21},
		from: false,
		to: false,
		initial: false,
		setInitial: false,
		updateElement: true,
		draggable: false,
		firstday: 0,
		klass: 'datePicker',
		days: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'],
		daysShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
		months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
		onShow: function(container){
			container.setStyle('display','block');
		},
		onHide: function(container){
			container.setStyle('display','none');
		}
		/*onUpdate: $empty*/
	},

	initialize: function(el,options){
		this.el = el;
		this.setOptions(options);
		this.current = this.options.initial ? new Date(this.options.initial[0],this.options.initial[1],this.options.initial[2]) : (this.options.from ? new Date(this.options.from[0],this.options.from[1],this.options.from[2]) : new Date());
		this.limit = {from:false,to:false};
		this.open = false;

		// DOM
		var tr;
		this.dom = {days:[]};
		//this.dom.container = new Element('div',{'class':this.options.klass}).setStyle('display','none').inject(document.body);
		this.dom.container = new Element('div',{'class':this.options.klass}).setStyle('display','none').inject($(this.el.get('id') + '-container'));
			var handle = new Element('div',{'class':'handle'}).inject(this.dom.container);
			var body = new Element('div',{'class':'body'}).inject(this.dom.container);
			new Element('div',{'class':'close'}).set('html','').adopt(new Element('ins')).addEvent('click',this.hide.bind(this)).inject(body);
			
			var htmlContainer = new Element('div', {'class':'container'})
			body.adopt(
				new Element('div', {'class': 'corner-container top'}).adopt(
					new Element('div', {'class': 'dots-container'}).adopt(new Element('ins', {'class': 'dots'}).adopt(new Element('ins'))),
					new Element('div', {'class': 'spacer'}),
					new Element('div', {'class': 'corner left'}).adopt(new Element('ins')),
					new Element('div', {'class': 'corner right'}).adopt(new Element('ins'))
				),
				htmlContainer.adopt(
					new Element('div', {'class': 'corner-container middle'}).adopt(
						new Element('div', {'class': 'corner left'}),
						new Element('div', {'class': 'corner right'})
					)
				),
				new Element('div', {'class': 'corner-container bottom'}).adopt(
					new Element('div', {'class': 'spacer'}),
					new Element('div', {'class': 'corner left'}).adopt(new Element('ins')),
					new Element('div', {'class': 'corner right'}).adopt(new Element('ins'))
				)
			);
			
			var table = new Element('table').inject(htmlContainer);
				var thead = new Element('thead').inject(table);
					tr = new Element('tr').inject(thead);
						this.dom.month = new Element('ins',{'class':'month'}).inject(new Element('td',{colspan:4, 'styles': {'width': 'auto'}}).inject(tr));
						this.dom.monthDown = new Element('span',{'class':'down'}).addEvent('click',this.walk.bind(this,['Month',-1,'monthDown'])).adopt(new Element('ins'));
						this.dom.monthUp = new Element('span',{'class':'up'}).addEvent('click',this.walk.bind(this,['Month',1,'monthUp'])).adopt(new Element('ins'));
						new Element('div',{'class':'incdec'}).adopt(new Element('ins',{'class':'bg'}),this.dom.monthDown,this.dom.monthUp).injectAfter(this.dom.month);
						this.dom.year = new Element('ins',{'class':'year'}).inject(new Element('td',{colspan:3, 'styles': {'width': 'auto'}}).inject(tr));
						this.dom.yearDown = new Element('span',{'class':'down'}).addEvent('click',this.walk.bind(this,['FullYear',-1,'yearDown'])).adopt(new Element('ins'));
						this.dom.yearUp = new Element('span',{'class':'up'}).addEvent('click',this.walk.bind(this,['FullYear',1,'yearUp'])).adopt(new Element('ins'));
						new Element('div',{'class':'incdec'}).adopt(new Element('ins',{'class':'bg'}),this.dom.yearDown,this.dom.yearUp).injectAfter(this.dom.year);
					tr = new Element('tr').inject(thead);
						var day = this.options.firstday;
						for(var i=0;i<7;i++){
							//new Element('th').set('html',this.options.days[day].substr(0,1)).inject(tr);
							new Element('th').set('html',this.options.daysShort[day]).inject(tr);
							
							day += day>5?-6:1;
						}
				var tbody = new Element('tbody').inject(table);
					var i = 0;
					for(var y=0;y<6;y++){
						tr = new Element('tr').inject(tbody);
						for(var x=0;x<7;x++){
							this.dom.days[i] = new Element('td').addEvent('click',this.select.bind(this,[i])).inject(tr);
							i += 1;
						}
					}

		if(this.options.draggable){
			this.dom.container.makeDraggable({handle:handle.setStyle('cursor','move')});
		}

		this.deselect();

		if(this.options.initial && this.options.setInitial){
			this.setFullDate(this.options.initial[0],this.options.initial[1],this.options.initial[2]).update();
		}
	},

	walk: function(ref,increment,but){
		if(!ref || !this.dom[but].hasClass('disabled')){
			if(ref){
				this.current['set'+ref](this.current['get'+ref]()+increment);
			}
			this.limit = {from:false,to:false};
			var now = this.parse();
			[['from','Down',true],['to','Up',false]].each(function(arr){
				var ybut = this.dom['year'+arr[1]].removeClass('disabled');
				var mbut = this.dom['month'+arr[1]].removeClass('disabled');
				if(this.options[arr[0]]){
					var cmp = this.options[arr[0]].associate(['y','m','d']);
					if((arr[2] && now.y<=cmp.y) || (!arr[2] && now.y>=cmp.y)){
						ybut.addClass('disabled');
						if((arr[2] && now.y<cmp.y) || (!arr[2] && now.y>cmp.y)){
							this.current.setFullYear(cmp.y,cmp.m,cmp.d);
							this.limit[arr[0]] = true;
						}else if((arr[2] && now.m<=cmp.m) || (!arr[2] && now.m>=cmp.m)){
							mbut.addClass('disabled');
							this.current.setMonth(cmp.m);
							this.limit[arr[0]] = true;
						}
					}
				}
			},this);
			this.build();
		}
	},

	build: function(){
		var date = this.parse();

		//this.dom.month.innerHTML = this.options.months[date.m].substr(0,3).toUpperCase();
		this.dom.month.innerHTML = this.options.months[date.m];
		this.dom.year.innerHTML = date.y;

		var x0 = new Date(date.y,date.m,1).getDay();
		var x1 = new Date(date.y,date.m+1,0).getDate();

		x0 += x0-this.options.firstday<0 ? 7-this.options.firstday : -this.options.firstday;

		var day, atr;
		for(i=0;i<42;i++){
			day = i-x0+1;
			atr = ['',''];
			if(day>0 && day<=x1){
				if((this.limit.from && day<this.options.from[2]) || (this.limit.to && day>this.options.to[2])){
					atr = [day,'disabled'];
				}else if(date.y==this.selected.date.y && date.m==this.selected.date.m && day==this.selected.date.d){
					atr = [day,'selected'];
					this.selected.index = i;
				}else{
					atr = [day,'selectable'];
				}
			}
			this.dom.days[i].set('html',atr[0]).className = atr[1];
		}
	},

	select: function(i){
		if(this.dom.days[i].hasClass('selectable')){
			this.dom.days[i].className = 'selected';
			this.current.setDate(this.dom.days[i].innerHTML.toInt());
			if(this.selected.index && this.selected.date.y==this.current.getFullYear() && this.selected.date.m==this.current.getMonth()){
				this.dom.days[this.selected.index].className = 'selectable';
			}
			this.selected = {date:this.parse(),index:i};
			this.update();
			this.hide();
		}else if(this.dom.days[i].hasClass('selected')){
			this.hide();
		}
	},

	deselect: function(){
		this.selected = {date:{y:0,m:0,d:0},index:false};
		this.walk();
		return this;
	},

	update: function(){
		if(this.options.updateElement){
			this.el[$defined(this.el.value)?'value':'innerHTML'] = this.selected.index===false ? '' : this.format();
		}
		this.fireEvent('update',[this.selected.date]);
		return this;
	},

	show: function(){
		if(!this.open){
			this.open = true;
			var s = this.el.getCoordinates();
			var offsetX = this.el.getSize().x / 2 + 54;
			if (Browser.Engine.trident4) offsetX -= 4;
			var offsetY = this.el.getSize().y;
			//this.dom.container.setStyles({left: s[this.options.position.x] + this.options.offset.x, top: s[this.options.position.y] + this.options.offset.y, display: 'block'});
			this.dom.container.setStyles({right: -(this.options.offset.x + offsetX), top: this.options.offset.y + offsetY, display: 'block'});
			this.fireEvent('show', [this.dom.container, this.el, this.options.position, this.options.offset]);
		}
		return this;
	},

	hide: function(){
		if(this.open){
			this.open = false;
			this.fireEvent('hide',[this.dom.container,this.el]);
		}
		return this;
	},

	parse: function(){
		return [this.current.getFullYear(),this.current.getMonth(),this.current.getDate()].associate(['y','m','d']);
	},

	setFullDate: function(y,m,d){
		this.current.setFullYear(y,m,d);
		this.selected.date = this.parse();
		this.walk();
		return this;
	},

	format: function(ymd,format){
		ymd = ymd ? ($type(ymd)=='array' ? ymd.associate(['y','m','d']): ymd) : this.selected.date;
		var date = new Date(ymd.y,ymd.m,ymd.d);
		return (format || this.options.format).
		replace(/%d/g,(date.getDate()<10?'0'+date.getDate():date.getDate())).
		replace(/%DD/g,this.options.days[date.getDay()]).
		replace(/%D/g,this.options.days[date.getDay()].substr(0,3)).
		replace(/%m/g,(date.getMonth()+1<10?'0'+(date.getMonth()+1):date.getMonth()+1)).
		replace(/%MM/g,this.options.months[date.getMonth()]).
		replace(/%M/g,this.options.months[date.getMonth()].substr(0,3)).
		replace(/%y/g,(date.getFullYear()+'').substr(2)).
		replace(/%Y/g,date.getFullYear());
	}
});

Element.implement({
	datePicker: function(options,event){
		var dp = new datePicker(this,options);
		this.addEvent((event||'focus'),dp.show.bind(dp));
		this.store('dp',dp);
		return dp;
	}
});
