//	Mootools Events Calendar v0.3.0 (2009-08-05) - http://dansnetwork.com/mootools/events-calendar

/*
	Script: mooECal.js
		Class for creating an events calendar with multiple views
	
	Requires:
		Mootools 1.2.3 Core
		Mootools 1.2.3.1 More
			Date

	License:
		MIT-style license.
*/
var Calendar = new Class({
	
	Implements: [Options, Events],
	options: {
		calContainer: 'calBody', // id of the element that the calendar will be "injected" into
		newDate: 0, // used to set the initial selected date to one other than the current day
		feedPlugin: '', // default (empty string) uses cEvents[] for manual event entry
		feedSpan: 3, // This is the number of months (past and future) of events to retrieve. Not needed for manual event entry using cEvents.
		weekStart: 0, // Sets the first day of the week (0 = Sunday and 1 = Monday)
		cEvents: [] //event container
	},
	initialize: function(options){
		this.setOptions(options);
		this.extendDate();
		this.days = ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'];
		this.months = ['январь', 'февраль', 'март', 'апрель', 'май', 'июнь', 'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь'];
		this.daysInMonth = 30; // can be set with setDaysInMonth(month,year)
		this.options.newDate != 0 ? this.calDate = new Date(this.options.newDate) : this.calDate = new Date();
		this.startingOffset = 0; // determine the offset of the first of the month and Sunday - used for the "month" view
		this.viewStartDate = new Date(); // starting date for current view
		this.viewEndDate = new Date(); // ending date for current view
		this.eventRangeStart = new Date(); //current range of events that have been fetched
		this.eventRangeEnd = new Date();
		this.setCalParams();
		
		this.showControlsRow().replaces($('calendar-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1)).getFirst().getFirst());
	},
	setDaysInMonth: function(month, year){ // month: must be an integer (0 - 11) year: used to dertermine if leap year exists
		this.daysInMonths = [31,28,31,30,31,30,31,31,30,31,30,31];
		if(new Date(year,1,29).getDate() == 29) // determine if leap year
			this.daysInMonths[1] = 29;
		this.daysInMonth = this.daysInMonths[month];
	},
	setStartingOffset: function(month,year){ // month: must be an integer (0 - 11)
		this.options.weekStart == 0 ? this.startingOffset = new Date(year,month,1).getDay() : this.startingOffset = (new Date(year,month,1).getMDay());
	},
	setDate: function(day){
		this.calDate.setDate(day);
	},
	setCalParams: function(){
		this.setDaysInMonth(this.calDate.getMonth(), this.calDate.getFullYear());
		this.setStartingOffset(this.calDate.getMonth(), this.calDate.getFullYear());
	},
	showControlsRow: function(){
		var trC = new Element('tr');
		var thC = new Element('th', {'colspan': '7'}).inject(trC);
		
		var sPrevCal = new Element('span', {
			'class': 'prev month',
			'html': '&#9664;'
		}).inject(thC);

		var liHeaderCal = new Element('span').set('html', this.showCalTitle()).inject(thC);

		var sNextCal = new Element('span', {
			'class': 'next month',
			'html': '&#9654;'
		}).inject(thC);

		sPrevCal.addEvent('click', this.showPrevMonth.bindWithEvent(this));
		sNextCal.addEvent('click', this.showNextMonth.bindWithEvent(this));

		return trC;
	},
	showDowRow: function(){
		var tr = new Element('tr');
		for (var i = 0; i < 7; i++){
			if (this.options.weekStart == 0) {
				new Element('th').set('text', this.days[i]).inject(tr);
			}
			else{
				var j = 0;
				if(i == 6){
					j = 0;
				}
				else{
					j = i+1;
				}
				new Element('th').set('text',this.days[j]).inject(tr);
			}
		}
			
		return tr;
	},
	showNextMonth: function(){
		this.lastCal = $('calendar-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1));
		
		this.calDate.nextMonth();
		
		this.showMonth();
	},
	showPrevMonth: function(){
		this.lastCal = $('calendar-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1));
		
		this.calDate.prevMonth();
		
		this.showMonth();
	},
	showMonth: function(){
		if ($('calendar-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1))){
			this.lastCal.setStyle('display', 'none');
			$('calendar-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1)).setStyles({display: '', opacity: 1.0});
			return;
		} else {
			this.lastCal.fade('out');
		}
		
		this.setCalParams();
		
		var table = new Element('table',{
			cellspacing: 0,
			id: 'calendar-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1),
			opacity: 0
		});
		var thead = new Element('thead').inject(table);
		var tbody = new Element('tbody').inject(table);
		
		this.showControlsRow().inject(thead);
		
		this.showDowRow().inject(thead);
		
		var calDone = false;
		for (var i = 0; i < 6; i++){
			if(calDone){
				break;
			}
			var tr = new Element('tr').inject(tbody); // create weeks
			
			var daysInPrevMonth = this.daysInMonths[(this.calDate.getMonth() || 12) - 1];
			for (var j = 0; j < 7; j++) {
				var day = ((j+1) + (i*7)) - this.startingOffset;
				var td = new Element('td').inject(tr); // create days
				if (day > 0 && day <= this.daysInMonth){
					td.set('id', 'day-' + this.calDate.getFullYear() + '-' + (this.calDate.getMonth() + 1) + '-' + day);
					
					td.store('date', day);
					
					new Element('span', {text: day}).store('date',day).inject(td);

					if(day == this.daysInMonth)
						calDone = true;
				} else {
					if (day > this.daysInMonth){
						td.adopt(new Element('span', {text: day - this.daysInMonth}));
					} else {
						td.adopt(new Element('span', {text: daysInPrevMonth + day}));
					}
					td.addClass('disabled');
				}
			}
		}
		
		this.viewStartDate.setTime(this.calDate.valueOf());
		this.viewStartDate.setDate(1);
		this.viewEndDate.setTime(this.calDate.valueOf());
		this.viewEndDate.setDate(this.daysInMonth);
		this.viewStartDate.clearTime();
		this.viewEndDate.endOfDay();
		
		new Request.JSON({
			url: '/events/' + this.calDate.getFullYear() + '/' + (this.calDate.getMonth() + 1 < 10 ? '0' : '') + (this.calDate.getMonth() + 1) + '/',
			onSuccess: (function(events){
				this.options.cEvents = events;
				this.lastCal.setStyle('display', 'none');
				table.inject($(this.options.calContainer));
				this.getCalEvents();
				table.fade('in');
			}).bind(this)
		}).send();
	}, // end of showMonth
	
	showCalTitle: function(){
		return this.months[this.calDate.getMonth()] + ' ' + this.calDate.getFullYear() + ' года';
	},
	
	getCalEvents: function(){
		this.loadCalEvents();
	},
	
	loadCalEvents: function(){
		for(var i = 0; i < this.options.cEvents.length; i++){
			var eStart = new Date().clearTime();
			var eEnd = new Date().clearTime();
			eStart.parse(this.options.cEvents[i].start);
			eEnd.parse(this.options.cEvents[i].end);
			if((eStart >= this.viewStartDate && eStart <= this.viewEndDate) || (eEnd >= this.viewStartDate && eEnd <= this.viewEndDate)){
				while(eStart <= eEnd){
					if (eStart >= this.viewStartDate && eStart <= this.viewEndDate) {
						var label = $('day-' + eStart.getFullYear() + '-' + (eStart.getMonth() + 1) + '-' + eStart.getDate()).getFirst('span');
						
						if (label){
							new Element('a', {
								href: '/events/' + eStart.getFullYear() + '/' + (eStart.getMonth() + 1 < 10 ? '0' : '') + (eStart.getMonth() + 1) + '/' + (eStart.getDate() < 10 ? '0' : '') + eStart.getDate() + '/'
							}).adopt(new Element('span', {text: eStart.getDate()})).replaces(label);
						}
					}
					eStart.increment();
				}
			}
		}
	},
	extendDate: function(){ // this section could also be implemented with MooTools::Implement (no pun intended)
		function prevMonth(){
			var thisMonth = this.getMonth();
			this.setMonth(thisMonth-1);
			if(this.getMonth() != thisMonth-1 && (this.getMonth() != 11 || (thisMonth == 11 && this.getDate() == 1))){
				this.setDate(0);
			}
		};
		function nextMonth(){
			var thisMonth = this.getMonth();
			this.setMonth(thisMonth+1);
			if(this.getMonth() != thisMonth+1 && this.getMonth() != 0)
				this.setDate(0);
		};
		function endOfDay(){
			this.setHours(23);
			this.setMinutes(59);
			this.setSeconds(59);
			this.setMilliseconds(999);
		};
		function getMDay(){ // the equivalent of Date.getDay() for weeks starting on Monday
			if(this.getDay() == 0)
				return 6;
			else
				return this.getDay() - 1;
		};
		function ymd(){
			return this.format('%Y-%m-%d');
		}
		function thTime(){ // twelve hour time
			var ampm = this.format('%p').toLowerCase();
			return this.format('%I:%M'+ampm);
		}

		Date.prototype.nextMonth = nextMonth;
		Date.prototype.prevMonth = prevMonth;
		Date.prototype.endOfDay = endOfDay;
		Date.prototype.getMDay = getMDay;
		Date.prototype.ymd = ymd;
		Date.prototype.thTime = thTime;
	}
	
});

