/**
 * Mootools kalendář
 * author: Jakub Truneček <jakub.trunecek@b2m.cz>
 * description:
 *
 * Options:
 *
 * Example:
 *
 */

var __calendars__ = new Object();

mCalendar = new Class({
	container: null,
	displayed: false,
	noHide: false,
	noFocus: false,
	element: null,
	options: {
		onShow: function(calendar){
			calendar.setStyle('visibility', 'visible');
			if (window.ie) {
				this.hidder.setStyle('visibility', 'visible');
			}
		},
		onHide: function(calendar){
			calendar.setStyle('visibility', 'hidden');
			if (window.ie) {
				this.hidder.setStyle('visibility', 'hidden');
			}
		},
        days : ['Neděle', 'Pondělok', 'Úterok', 'Strieda', 'Štvrtok', 'Piatok', 'Sobota'],
        months : ['Január', 'Február', 'Marec', 'Apríl', 'Máj', 'Jún', 'Júl',
			 'August', 'September', 'Október', 'November', 'December'],
		lettersDay : 2,
		dateFormat : '%d.%m.%Y',
		firstDayInWeek : 1,
		className : 'calendar',
		daysInMonth : [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
		showDelay: 0,
		showDelayIfDisplayed: 0,
		hideDelay: 0
    },

    initialize: function(elements, options) {
		this.id = $time() + '__calnedar__';
		__calendars__[this.id] = this;
		if (window.ie) {
			this.hidder = new Element('iframe', {
				styles: {
					'visibility' : 'hidden',
					'position' : 'absolute',
					'top' : '0',
					'left' : '0'
				}
			}).inject(document.body);
		}
		this.setOptions(options);
		this.calendar = new Element('div', {
			'class': this.options.className + '-container',
			'styles': {
				'position': 'absolute',
				'top': '0',
				'left': '0',
				'visibility': 'hidden'
			}
		}).inject(document.body);
		this.wrapper = new Element('div').inject(this.calendar);
		$$(elements).each(this.build, this);
		if (this.options.initialize) this.options.initialize.call(this);
	},

	build: function(el){
		if (el.getTag() == 'input' &&  el.getAttribute('type') == 'text') {
			el.addEvent('focus', function(event){
        		if (!this.noFocus) {
					this.element = el;
					timer = this.start.delay(200, this, [el]);
				}
				this.noFocus = false;
			}.bind(this));
			el.addEvent('click', function(event){
        		if (!this.noFocus) {
					this.element = el;
					timer = this.start.delay(200, this, [el]);
				}
				this.noFocus = false;
			}.bind(this));

			var end = this.end.bind(this, [el]);
			el.$tmp.object = this;
			this.calendar.$tmp.object = this;
			this.calendar.addEvent('click', function(e){
				e = new Event(e);
				this.noHide = true;
				this.noFocus = true;
			}.bind(this));
			el.addEvent('blur', function(e){
			    e = new Event(e);
				timer = end.delay(200, this, [e.target]);
			});
			el.addEvent('trash', end);
		}
	},

	end: function(el){
		if (!this.noHide) {
			$clear(this.timer);
			this.timer = this.hide.delay(this.options.hideDelay, this, [el]);
		} else {
			el.focus();
			this.noHide = false;
		}
	},

	start: function(el){
		el.$tmp.date = this.dateFromStr(el.value);
		this.timer = this.show.delay(((this.displayed) ? this.options.showDelayIfDisplayed : this.options.showDelay), this, [el]);
	},

	position: function(element){
		var pos = element.getCoordinates();
		this.calendar.setStyles({
			'left': pos.left,
			'top': pos.bottom
		});
	},

	getTable: function(el){
		month = this.options.months[el.$tmp.date.getMonth()];
		innerHTML = ('<table cellspacing="0" cellpading="0" class="'+this.options.className+'-dateSelect"><tbody><tr><td style="cursor: pointer; _cursor: hand;" onclick="__calendars__[\''+this.id+'\'].setMonth(-1);">&laquo;</td><td>'+month+' '+el.$tmp.date.getFullYear()+'</td><td style="cursor: pointer; _cursor: hand;" onclick="__calendars__[\''+this.id+'\'].setMonth(1);">&raquo;</td></tr></tbody></table>');

		date = el.$tmp.date;
		/**
		 * Prestupny rok
		 */
		this.options.daysInMonth[1] = (date.getFullYear() % 4 == 0) ? 29 : 28;

		/**
		 * Hlavicka dni
		 */
		innerHTML += '<table cellspacing="0" cellpading="0" class="'+this.options.className+'-mainTable"><thead><tr>';
		for(i = 0; i <= 6; i++) {
			index = (i+this.options.firstDayInWeek) % 7;
			innerHTML += ('<td>'+this.options.days[index].substr(0, this.options.lettersDay)+'</td>');
		}
		innerHTML += '</tr></thead>';

		// Jaky je prvni den v mesici
		date.setDate(1);
		firstDay = (date.getDay()-this.options.firstDayInWeek) % 7;
		if (firstDay < 0) {
			firstDay += 7;
		}

		innerHTML += '<tbody>'
		/**
		 * Formatovani dni, nejprve do pole
		 */
		days = new Array();
		for (i = 1; i <= this.options.daysInMonth[date.getMonth()]; i++) {
            days.push(i);
		}
		if (firstDay == 0) {
			to = 7;
		} else {
			to = firstDay;
		}
		$tmp = new Array();
		date.setDate(1);
		for (i = 0; i < to; i++) {
			date.setDate(date.getDate()-1);
            $tmp.push(date.getDate());
		}
		$tmp = $tmp.reverse();
		$tmp.extend(days);
		days = $tmp;
		/**
		 *  Nastavit datum zpět na prvního v měsící, a následně na posledního v měsící
		 */
        date.setDate(1);
        date.setMonth(date.getMonth()+1);
		date.setDate(this.options.daysInMonth[date.getMonth()]);
		for (i=days.length; i<42; i++) {
			date.setDate(date.getDate()+1);
			days.push(date.getDate());
		}
		/**
		 *  Nastavit datum zpět na prvního v měsící
		 */
        date.setDate(1);
        date.setMonth(date.getMonth()-2);
		/**
		 * Dny jsou vyrenderovany
		 */
		addClass = 'prevMonth';
		selected = this.dateFromStr(el.value);
		for (i = 0; i < days.length; i++) {
			classes = new Array();
			if(days[i] == 1) {
				date.setDate(1);
				if (addClass == 'prevMonth') {
					addClass = 'actualMonth'
				} else {
					addClass = 'nextMonth'
				}
				date.setMonth(date.getMonth()+1);
			}
			classes.push(addClass);
			date.setDate(days[i]);
			if (date.getDay() == 0 || date.getDay() == 6) {
				/* Jedna se o vikend */
				classes.push('weekend');
			}

			today = new Date();
			if (date.getDate() == today.getDate() && date.getMonth() == today.getMonth() &&
			    date.getFullYear() == today.getFullYear()) {
                classes.push('today');
			}

			if (el.value != '') {
				if (date.getDate() == selected.getDate() && date.getMonth() == selected.getMonth() &&
				    date.getFullYear() == selected.getFullYear()) {
	                classes.push('selected');
				}
			}

			className = classes.join(' ');
			if(i % 7 == 0) {
    			innerHTML += '<tr>'
			}
   			innerHTML += '<td style="cursor: pointer; _cursor: hand;" onclick="__calendars__[\''+this.id+'\'].setDate('+date.getTime()+')" class="'+className+'">'+days[i]+'</td>';
			if(i % 7 == 6) {
            	innerHTML += '</tr>'
			}
		}
		innerHTML += '</tbody></table>'
		this.wrapper.setHTML(innerHTML);
	},

	setDate: function(time) {
		selectedDate = new Date();
		selectedDate.setTime(time);
		var outputDate = this.options.dateFormat;
		outputDate = outputDate.replace(/(%d)/, (selectedDate.getDate().toString().length == 1) ? '0' + selectedDate.getDate().toString() : selectedDate.getDate().toString());
		outputDate = outputDate.replace(/(%m)/, ((selectedDate.getMonth() + 1).toString().length == 1) ? '0' + (selectedDate.getMonth() + 1).toString() : (selectedDate.getMonth() + 1).toString());
		outputDate = outputDate.replace(/(%Y)/, selectedDate.getFullYear());
		this.element.value = outputDate;
		this.end(this.element);
	},

	setMonth: function(count) {
		this.element.$tmp.date.setMonth(this.element.$tmp.date.getMonth()-1+count)
		this.getTable.delay(50, this, [this.element]);
	},

	/**
	 * Ze zadaneho retezce vrati cas, pokud je retezec prazdny, vrati aktualni datum.
	 */
	dateFromStr: function(date) {
		result = new Date();
		if (date == "") {
			return result;
		}
		positionsSplit = this.options.dateFormat;
		positionsSplit = positionsSplit.replace(/[^%dmY]/g, '');
		positionsSplit = positionsSplit.split('%');
		positions = new Array();
		for (i = 1; i < 4; i++) {
			if (positionsSplit[i] == 'Y') {
				positions[0] = i;
			}
			if (positionsSplit[i] == 'm') {
				positions[1] = i;
			}
			if (positionsSplit[i] == 'd') {
				positions[2] = i;
			}
		}
		reg = this.options.dateFormat;
		reg = reg.replace(/(%d)/, '([0-9]{2})');
		reg = reg.replace(/(%m)/, '([0-9]{2})');
		reg = reg.replace(/(%Y)/, '([0-9]{4})');
		reg = reg.replace(/([\.\+\?\\])/g, '\\$1');
		reg = new RegExp(reg);
		date = date.match(reg);
		result.setYear(date[positions[0]]);
		result.setMonth((date[positions[1]] - 1));
		result.setDate((date[positions[2]]));
		return result;
	},

	show: function(el){
		this.displayed = true;
		this.wrapper.empty();
		this.position(el);
		this.getTable(el);
		if (window.ie) {
			coor = this.calendar.getCoordinates();
			this.hidder.setStyles({
			    'left' : coor.left,
			    'top' : coor.top,
			    'width' : coor.width,
			    'height' : coor.height
			});
		}
		if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this);
		this.fireEvent('onShow', [this.calendar]);
	},

	hide: function(el){
			this.displayed = false;
			this.fireEvent('onHide', [this.calendar]);
	}

});
mCalendar.implement(new Events, new Options);
