/**
* @author Alexey
**/
creocal = Class.create();

creocal.prototype = {
	/*
	* Root element
	*/
	root : null,
	/*
	* Tbody of table for dates
	*/
	calendarTableBody: null,
	/*
	* Current Date
	*/
	currentDate: new Date(),
	/*
	* Control Elements
	*/
	curDateElements: new Array(),
	/*
	* Events array
	* [year][month][day] = array(...data...)
	*/
	eventsData : new Array(),
	/*
	* Constructor
	*/
	initialize : function(el) {
		this.root = el;

		var cc = $$('table.calendarData');
		for(var i = 0; i < cc.length; i++)
		{
			var tbody = cc[i];
			if(tbody.descendantOf(this.root))
			{
				this.calendarTableBody = tbody;
				break;
			}
		}

		/****Curent date will put into .innerHTML****/
		var cc = $$('.curDate');
		for(var i = 0; i < cc.length; i++)
		{
			var el = cc[i];
			if(el.descendantOf(this.root))
			this.curDateElements.push(el);
		}

		/****Buttons****/
		var cc = $$('.nextYearNav');
		for(var i = 0; i < cc.length; i++)
		{
			var el = cc[i];
			if(el.descendantOf(this.root))
			Event.observe(el, 'click', this.nextYear.bindAsEventListener(this, el, this));
		}

		/****Buttons****/
		var cc = $$('.nextMonthNav');
		for(var i = 0; i < cc.length; i++)
		{
			var el = cc[i];
			if(el.descendantOf(this.root))
			Event.observe(el, 'click', this.nextMonth.bindAsEventListener(this, el, this.root));
		}

		/****Buttons****/
		var cc = $$('.previosMonthNav');
		for(var i = 0; i < cc.length; i++)
		{
			var el = cc[i];
			if(el.descendantOf(this.root))
			Event.observe(el, 'click', this.prevMonth.bindAsEventListener(this, el, this.root));
		}

		/****Buttons****/
		var cc = $$('.previosYearNav');
		for(var i = 0; i < cc.length; i++)
		{
			var el = cc[i];
			if(el.descendantOf(this.root))
			Event.observe(el, 'click', this.prevYear.bindAsEventListener(this, el, this));
		}


		this.root.url = this.root.getAttribute('url');
		
		this.showMonthData();
		if(this.root.url)
		this.loadEvents(this.root.url);

		//Error check
		if(!this.calendarTableBody)
		alert('Can not found tbody.calendarData for dates');

		//	  this.rowTemplateElement.hide();
	},
	detectStartEndDate : function()
	{
		var st = this.currentDate.firstDayOfMonth();
		var en = this.currentDate.lastDayOfMonth();
//		if(st.getDay() == SUNDAY)
//		st = st.subtractWeeks(1);
//		if(en.getDay() == 0)
//		en = en.subtractWeeks(1);
		st = st.subtractDays(st.getDay());
		en = en.addDays(6 - en.getDay());
		return {'start': st, 'end': en};
	},
	showMonthData : function()
	{
		this.clearCalendar();
		this.showCurDate();
		var dt = this.currentDate;
		var range = this.detectStartEndDate();

		for(var i = range.start; i <= range.end; i = i.addWeeks(1))
		{
			this.addRow(this.getWeekData(i), i);
		}
	},
	clearCalendar : function()
	{
		var rows = (this.calendarTableBody.tHead && this.calendarTableBody.tHead.rows.length > 0) ?
		$A(this.calendarTableBody.tBodies[0].rows) : $A(this.calendarTableBody.rows).without(this.calendarTableBody.rows[0]);

		for(var i = 0; i < rows.length; i++)
		this.calendarTableBody.deleteRow(rows[i].rowIndex);
	},
	getWeekData : function(dt)
	{
		var data = {};

		for(var i=0;i<7; i++, dt=dt.addDays(1))
		{
			data = this.getDayData(dt, data);
			if(dt.getDay() == SATURDAY)
			break;
		}

		return data;
	},
	getDayData : function(dt, data)
	{
		var ev;
		var str = dt.getDate();
		/*
		skip = true;
		try
		{
		ev = this.eventsData[dt.getFullYear()];
		ev = ev[dt.getMonth()+1];
		ev = ev[dt.getDate()];
		}
		catch(e)
		{
		skip = false;
		}

		if(skip && ev)
		{
		for(var i = 0; i < ev.length; i++)
		if(ev[0]['title'] && ev[0]['text'])
		str = str + '<br>' + "<a href=# onclick=\"creocal_showEvent('"+dt.format('%YYYY-%MM-%DD')+"', this);\">" + ev[0]['title'] + '</a>';
		}
		*/
		data[dt.getDayAbbreviation()] = str;
		return data;
	},
	addRow : function(data, dt)
	{
		var row = this.calendarTableBody.insertRow(-1);
		this.setDataIntoRow(row, data, dt);
	},
	setDataIntoRow : function(row, data, dt)
	{
		//ToDo: set data into el Tree
		this.calendarTableBody.tBodies[0].appendChild(row);
		for(var i = 0; i<7; i++,dt=dt.addDays(1))
		{
			var cell = row.insertCell(-1);
			this.seCellStyle(dt, cell);
			//			cell.onlick = creocal_showEvent;
			cell.width = '33';
			Event.observe(cell, 'click', creocal_showEvent.bindAsEventListener(this, cell, dt));
			cell.innerHTML = data[dt.getDayAbbreviation()];
		}
	},
	nextMonth : function()
	{
//		var ob = getRootElByChild(this);
//		var ob = getRootElByChild(this);
//		ob = ob.creocal;
		ob = this;
		ob.currentDate = ob.currentDate.addMonths(1);
		ob.showMonthData();
	},
	nextYear : function()
	{
//		var ob = getRootElByChild(this);
//		ob = ob.creocal;
		ob = this;
		ob.currentDate = ob.currentDate.addYears(1);
		ob.showMonthData();
	},
	prevMonth : function()
	{
//		var ob = getRootElByChild(this);
//		ob = ob.creocal;
		ob = this;
		ob.currentDate = ob.currentDate.addMonths(-1);
		ob.showMonthData();
	},
	prevYear : function()
	{
//		var ob = getRootElByChild(this);
//		ob = ob.creocal;
		ob = this;
		ob.currentDate = ob.currentDate.addYears(-1);
		ob.showMonthData();
	},
	showCurDate : function()
	{
		for(var i=0; i < this.curDateElements.length; i++)
		{
			this.curDateElements[i].innerHTML = this.currentDate.format('%MMMM %YYYY');
		}
	},
	seCellStyle : function(dt, cell)
	{
		skip = true;
		try
		{
			ev = this.eventsData[dt.getFullYear()];
			ev = ev[parseInt(dt.getMonth())+1];
			ev = ev[parseInt(dt.getDate())];
		}
		catch(e)
		{
			skip = false;
		}

		if(skip && ev){
			//			if(ev.length > 1)
			//				Element.addClassName(cell, 'withevent');
			for(var i = 0; i < ev.length; i++)
			if(ev[i]['style'])
			{
				Element.addClassName(cell, ev[i]['style'].unescapeHTML().strip());
				break;
			}
		}
		else
		if((Now()).format('%YYYY-%MM-%DD') == dt.format('%YYYY-%MM-%DD'))	//Today
		Element.addClassName(cell, 'todayDate');
		else
		if(this.currentDate.getMonth() > dt.getMonth())						//Previos Month
		Element.addClassName(cell, 'previosMonth');
		else if(this.currentDate.getMonth() < dt.getMonth())				//Next month
		Element.addClassName(cell, 'nextMonth');
		else																//Current Month
		Element.addClassName(cell, 'currentMonth');
	},

	loadEvents : function(url)
	{
		window.to = this;
		new Ajax.Request(url,
		{   method: 'get',
		onSuccess: function(transport) {
			if (200 == transport.status) {
				var xml = transport.responseXML;
				if (typeof(DOMParser) != "undefined") {
					// Mozilla, Firefox, and related browsers
					xml = (new DOMParser()).parseFromString(transport.responseText, "application/xml");
				}
				else if (typeof(ActiveXObject) != "undefined") {
					// Internet Explorer.

					var doc = new ActiveXObject("Microsoft.XMLDOM");  // Create an empty document
					doc.loadXML(transport.responseText);            // Parse text into it
					xml = doc;                   // Return it
				}
				window.to.parseEvents(xml);
			}
		}
		});
	},
	parseEvents : function(xml)
	{
		var events = xml.getElementsByTagName('event');

		for(var i = 0; i < events.length; i++)
		this.parseEvent(events[i]);

		this.showMonthData();
	},
	parseEvent : function(event)
	{
		//		month
		var month = event.getElementsByTagName('month');
		month = parseInt(month[0].firstChild.nodeValue);
		//		day
		var day = event.getElementsByTagName('day');
		day = parseInt(day[0].firstChild.nodeValue);
		//		year
		var year = event.getElementsByTagName('year');
		year = year[0].firstChild.nodeValue;

		if(day && month && year)
		{
			if(!this.eventsData[year])
			this.eventsData[year] = new Array();
			if(!this.eventsData[year][month])
			this.eventsData[year][month] = new Array();
			if(!this.eventsData[year][month][day])
			this.eventsData[year][month][day] = new Array();
			var ev = new Array();
			//		title
			var d = event.getElementsByTagName('title');
			if(d.length) ev['title'] = d[0].firstChild.nodeValue;
			//		text
			var d = event.getElementsByTagName('text');

			if(d.length) ev['text'] = d[0].firstChild.nodeValue;

			//		popuplink
			//			var d = event.getElementsByTagName('popuplink');
			//			if(d.length) ev['popuplink'] = d[0].firstChild.nodeValue;
			//		style

			var d = event.getElementsByTagName('style');
			if(d.length && d[0].firstChild) ev['style'] = d[0].firstChild.nodeValue;

			//		tooltip
			//			var d = event.getElementsByTagName('tooltip');
			//			if(d.length) ev['tooltip'] = d[0].firstChild.nodeValue;
			//		script
			//			var d = event.getElementsByTagName('script');
			//			if(d.length) ev['script'] = d[0].firstChild.nodeValue;
			var rec = new Array();
			rec['recurtype'] = parseInt(getNodeValue(event, 'recurtype'));
			rec['recursuntil'] = getNodeValue(event, 'recursuntil');
			var res = rec['recursuntil'].match(/(\d+)-(\d+)-(\d+)/);
			if(res)
			rec['recursuntil'] = new Date(res[1], res[2]-1, res[3]);
			rec['eventdate'] = new Date(year, month-1, day);

			rec['every'] = getNodeValue(event, 'every');
			rec['monthlyoption'] = getNodeValue(event, 'monthlyoption');
			rec['pos'] = getNodeValue(event, 'pos');

			rec['days'] = new Array();
			rec['isHaveDay'] = 0;
			rec['isHaveDay'] |= rec['days']['sun'] = parseInt(getNodeValue(event, 'sun'));
			rec['isHaveDay'] |= rec['days']['mon'] = parseInt(getNodeValue(event, 'mon'));
			rec['isHaveDay'] |= rec['days']['tue'] = parseInt(getNodeValue(event, 'tue'));
			rec['isHaveDay'] |= rec['days']['wed'] = parseInt(getNodeValue(event, 'wed'));
			rec['isHaveDay'] |= rec['days']['thu'] = parseInt(getNodeValue(event, 'thu'));
			rec['isHaveDay'] |= rec['days']['fri'] = parseInt(getNodeValue(event, 'fri'));
			rec['isHaveDay'] |= rec['days']['sat'] = parseInt(getNodeValue(event, 'sat'));

			var tmp;
			try{
				tmp = this.eventsData[year][month][day].length;
			}
			catch(e)
			{
				tmp = 0;
			}

			if(rec['recurtype'] > 0)
			{
				var i = rec['eventdate'];
				var index = 0, fl_add = false;

				while(rec['recursuntil']-i >=0){

					switch(rec['recurtype']){
						case 1/*'daily'*/:
						if(!rec['every'])
							fl_add = 1;
						else if(!(index % rec['every']))
							fl_add = 1;
						break;
						case 2/*'weekly'*/:
						if(((Math.ceil(index/7) % rec['every']) == 0) && parseInt(rec['days'][i.getDayAbbreviation().toLowerCase()]))
							fl_add = 1;
						break;
						case 3/*'monthly'*/:
						
						try{
//						if(rec['pos'] < 5 && rec['days'][i.getDayAbbreviation().toLowerCase()])
//						{
//							var tmp = (i.dayNameOfMonthWithNumber(i.getDay(), rec['pos']) - i);
//							alert('lastDay:' + i.dayNameOfMonthWithNumber(i.getDay(), rec['pos'])
//							+ ' Cur: ' + i + ' pos: ' + rec['pos']
//							 + ' days:' + tmp + ' == ' + (tmp <= DAYS_CF)
//							 );
//						}
													
						if(((rec['eventdate'].getMonth() - i.getMonth()) % rec['every'] == 0) &&
						  ((!rec['isHaveDay'] && i.getDate() == rec['pos']) || 
							(
								//dayName of month with number
								(rec['pos'] > 0 && rec['pos'] < 5 && rec['days'][i.getDayAbbreviation().toLowerCase()] && Math.abs(i.dayNameOfMonthWithNumber(i.getDay(), rec['pos']) - i) < DAYS_CF)
								||
								//last day(mon,tue...)
								(rec['pos'] == 5 && rec['days'][i.getDayAbbreviation().toLowerCase()] && Math.abs(i.lastDayNameOfMonth(i.getDay(), rec['pos']) - i) < DAYS_CF)
							)
						  )
						)
							fl_add = 1;
						}
						catch(e){}
						break;

					}
					if(fl_add)
					{
						if(!this.eventsData[i.getFullYear()])
						this.eventsData[i.getFullYear()] = new Array();
						if(!this.eventsData[i.getFullYear()][i.getMonth()+1])
						this.eventsData[i.getFullYear()][i.getMonth()+1] = new Array();
						if(!this.eventsData[i.getFullYear()][i.getMonth()+1][i.getDate()])
						this.eventsData[i.getFullYear()][i.getMonth()+1][i.getDate()] = new Array();
						tmp = this.eventsData[i.getFullYear()][i.getMonth()+1][i.getDate()].length;
						this.eventsData[i.getFullYear()][i.getMonth()+1][i.getDate()][tmp] = ev;
						fl_add = 0;
					}
					i = i.addDays(1);
					index++;
				}//while
			} else
			this.eventsData[year][month][day][tmp] =ev;

			//		if($event['recurtype'] > 0)
			//		{//Recur
			//			$event['recurCheck'] = 1;
			//		switch ($event['recurtype'])
			//		{
			//			case 1/*'daily'*/:
			//				$event['recurtype'] = 'daily';
			//				if($event['every']){
			//					$event['dailyDays'] = $event['every'];
			//					$event['dailyOptions'] = 'EveryXDays';
			//				}
			//				elseif (!$every)
			//					$event['dailyOptions'] = 'WeekdaysOnly';
			//				break;
			//			case 2/*'weekly'*/:
			//					$event['recurtype'] = 'weekly';
			//					/*Every*/ $event['recWeekly'] = $event['every']; /* week(s)*/
			//
			//					foreach ($wdays as $key => $val)
			//						$event['recWeeklyDay'][$val] = $event[$val];
			//
			//				break;
			//			case 3/*'monthly'*/:
			//				$event['recurtype'] = 'monthly';
			//				if($event['monthlyOption'] == 1){
			//					$event['monthlyOption'] = 'Day';
			//					$event['monthlyDays'] = $event['pos'];/* Of every */$event['monthlyMonths'] = $event['every'];
			//
			//				}
			//				elseif($event['monthlyOption'] == 2){
			//					$event['monthlyOption'] = 'Month';
			//					/*every*/$event['monthlyMonthOrder'] = $event['pos']/*st*/;
			//					/*day*/foreach ($wdays as $key => $val)
			//						$event['monthlyMonthDOW'][$val] = $event[$val];
			//
			//					/*of every*/$event['monthlyMonthRepeat']/*month*/ = $event['every'];
			//				}
			//				break;
			//		}
			//		}


		}
	}
};

function creocal_showEvent(ev, ob, dt)
{
//	alert(this + '=' + ev + '=' + ob + '=' + dt);
	if(!$('eventsBox'))
		return;
//	var ob = getRootElByChild(this);
	var ob = this;
//	ob = ob.creocal;

	var year = dt.getFullYear();
	var month = dt.getMonth() + 1;
	var day = dt.getDate();
	skip = true;

	try
	{
		ev = ob.eventsData[year];
		ev = ev[parseInt(month)];
		ev = ev[parseInt(day)];
	}
	catch(e)
	{
		skip = false;
	}
	var str = month+'-'+day+'-'+year + '<br>';
	if(skip && ev)
	{
		for(var i = 0; i < ev.length; i++)
		if(ev[i]['text'])
		str += ev[i]['text'] /*+ '<br>---------------<br>'*/;
	}

	$('eventsBox').innerHTML = str;
}


function getRootElByChild(el)
{
	if(Element.hasClassName(el, 'creocal'))
	return el;
	else return getRootElByChild(el.parentNode);
}

function getNodeValue(doc, name){
	var d = doc.getElementsByTagName(name);
	if(d.length && d[0].firstChild)
	return d[0].firstChild.nodeValue;
}


var initff = function(){
	setTimeout('initf2()', 300);
}

var initf2 = function(){
	var c;
	$$('span.creocal').each(function(cal){
		if(!cal.creocal)
		{
			c = new creocal($(cal));
			$(cal).setAttribute('creocal', c);
		}
	});
}
Event.observe(window,'load',initff,false);


