/*******************************************************************************
*
* Calendar version 0.2
*
* @Author: Martin Oom, Eniac Data AB
*
* changelog:
* ==============================================================================
* 0.2: changed javascript framework from MochiKit to ExtJSCore
* 0.1: initial release 
*
*******************************************************************************/

Ext.ns('Ext.eniac');

// helper functions
function incMonth(ADateObject,ACount) {
	if (typeof(ADateObject) != 'object')
		throw ('ADateObject must be a date object');
		
	if (!ACount)
		ACount = 1;			
	else
		ACount = parseInt(ACount);
		
	var m = ADateObject.getMonth();	
	m += ACount;
	ADateObject.setMonth(m);
	return ADateObject;
}

function decMonth(ADateObject,ACount) {
	if (typeof(ADateObject) != 'object')
		throw ('ADateObject must be a date object');
		
	if (!ACount)
		ACount = 1;			
	else
		ACount = parseInt(ACount);
	return incMonth(ADateObject,-ACount);
}

Ext.eniac.Calendar = Ext.extend(Ext.util.Observable, {
/*******************************************************************************
* private declarations
*******************************************************************************/	
	parentElement: null,
	baseURL: null,
	displayDate: null,
	selectedDate: null,
	
	dateToString: function(ADate) {
		var y = ADate.getFullYear();
		var m = ADate.getMonth() + 1;
		if (m < 10)
			m = '0' + m;			
		var d = ADate.getDate();
		if (d < 10)
			d = '0' + d;
		return  y + '-' + m + '-' + d;
	},
	
	stringToDate: function(AString) {
		AString = AString + "";
		if (typeof(AString) != "string" || AString.length === 0)
			return null;
		var parts = AString.split('-');
		if (parts.length === 0)
			return null;
		var date = new Date(parts[0], parts[1] - 1, parts[2]);
		date.setFullYear(parts[0]);
		date.setMonth(parts[1] - 1);
		date.setDate(parts[2]);
		return date;
	},	
	
	renderCalendarHeader: function(AParentElement,ACalendarData) {
		var tr = Ext.DomHelper.append(AParentElement,{tag: 'tr', cls: 'header'},true);
		
		var def = {tag: 'th', cls: 'navigator prev_month'};
		var th = Ext.DomHelper.append(tr,def,true);
		th.on('click', function(oEvent) {
			//oEvent.stopEvent();
			this.doDecDisplayMonth();
		},this);
		
		var def = {tag: 'th', colspan: 6, html: ACalendarData.displayMonthName + ' - ' + ACalendarData.displayYear};
		Ext.DomHelper.append(tr,def);
		
		var def = {tag: 'th', cls: 'navigator next_month'};
		var th = Ext.DomHelper.append(tr,def,true);
		th.on('click', function(oEvent) {
			//oEvent.stopEvent();
			this.doIncDisplayMonth();
		},this);
	},
	
	renderCalendarBody: function(AParentElement,ACalendarData) {
		var weekdays = ['m','t','o','t','f','l','s'];
		
		var tr = Ext.DomHelper.append(AParentElement,{tag: 'tr'},true);
		
		Ext.DomHelper.append(tr,{tag: 'td'});
		
		Ext.each(weekdays,function(oItem, nIndex, arrAllItems){
			Ext.DomHelper.append(tr,{tag: 'td', cls: 'weekday_cell', html: oItem});
		},this);
		
		// TODO: replace with Ext.each
		for (var i = 0; i < ACalendarData.weeks.length; i++) {
			var today = new Date();
			var tr = Ext.DomHelper.append(AParentElement,{tag: 'tr'},true);			
			Ext.DomHelper.append(tr,{tag: 'td', cls: 'weekno_cell', html: ACalendarData.weeks[i].weekNo});
			for (var j = 0; j < ACalendarData.weeks[i].days.length; j++) {
				var dayData = ACalendarData.weeks[i].days[j];
				var cls = 'day_cell';
				if (dayData.isRedDay)
					cls += ' red_day';
				if (dayData.date == this.dateToString(this.selectedDate))
					cls += ' selected';	
				if (dayData.date == this.dateToString(today))
					cls += ' today';				
									
				var def = {
					tag: 'td',
					cls: cls,
					html: dayData.dayNo,
					title: (dayData.dayText ? dayData.dayText : '')		
				};
				var td = Ext.DomHelper.append(tr,def,true);
				td.on(
					'click', 
					this.doSelectDate.createDelegate(this,[this.stringToDate(dayData.date)]),
					this);
			}
		}
	},
	
	renderCalendarFooter: function(AParentElement,ACalendarData) {
		var today = new Date();
		var tr = Ext.DomHelper.append(AParentElement,{tag: 'tr', cls: 'footer'},true);
		var td = Ext.DomHelper.append(tr,{tag: 'td', colspan: 8},true);
		var def = {
			tag: 'a', 
			href: 'javascript:void(0);',
			html: 'Idag (' + this.dateToString(today) + ')'
		};
		var a = Ext.DomHelper.append(td,def,true);
		a.on('click',function(oEvent) {
			//oEvent.stopEvent();
			var today = new Date();
			this.doSelectDate(today);
		},this);
	},	
	
	render: function(ACalendarData) {
		var def = {
			tag: 'table',
			cls: 'Calendar',
			cellspacing: 0, 
			cellpadding: 0,
			children: [     
				{tag: 'thead', html: ''},
				{tag: 'tbody', html: ''},
				{tag: 'tfoot', html: ''}
			]
		};
		
		var table = Ext.DomHelper.overwrite(this.parentElement,def,true);				
		var tbody = Ext.DomQuery.selectNode('tbody',Ext.getDom(table));
		this.renderCalendarHeader(tbody,ACalendarData);		
		this.renderCalendarBody(tbody,ACalendarData);
		this.renderCalendarFooter(tbody,ACalendarData);
	},
	
	doSelectDate: function(ADate) {
		if (typeof(ADate) == 'string')
			ADate = this.stringToDate(ADate);
		if (typeof(ADate) != 'object')
			throw ('ADate must be a date object');
		
		this.selectedDate = ADate;
		this.update();
		this.fireEvent('selectDate',this,ADate);
	},
	
	doDecDisplayMonth: function() {		
		this.displayDate = decMonth(this.displayDate);
		this.update();
	},
	
	doIncDisplayMonth: function() {
		this.displayDate = incMonth(this.displayDate);		
		this.update();
	},

/*******************************************************************************
* public declarations
*******************************************************************************/	
	constructor: function(AParentElement, ABaseURL, AConfig) {
		AConfig = AConfig || {};
		Ext.apply(this, AConfig);
		Ext.eniac.DateSelector.superclass.constructor.call(this, AConfig);
		
		this.addEvents(
			'selectDate'
		);
		
		this.parentElement = Ext.get(AParentElement);
		this.baseURL = ABaseURL;
		
		this.displayDate = new Date();
		this.displayDate.setDate(1);
		
		this.selectedDate = new Date();		
	},
	
	update: function() {
		Ext.Ajax.request({
			url: this.baseURL + '?page=json_calendar&displayDate=' + this.dateToString(this.displayDate),
			/* would like to use params in this way but ExtJS says no... */
			/*params: {page: 'json_calendar', displayDate: this.dateToString(this.displayDate)},*/		
			method: 'get',
			scope: this,			
			success: function(oResponse, oOptions) {
				var data = Ext.decode(oResponse.responseText);
				this.render(data);				
			},
			failure: function(oResponse, oOptions) {
				Ext.DomHelper.overwrite(this.parentElement,'Kunde inte hämta kalenderinformation...');
			}
		});
	},
	
	setDisplayDate: function(ADate) {
		if (typeof(ADate) == 'string')
			ADate = this.stringToDate(ADate);
		if (ADate) {
			ADate.setDate(1);
			this.displayDate = ADate;	
		}
// TODO: if visible => update		
	},
	
	getSelectedDate: function() {
		return this.dateToString(this.selectedDate);
	},
	
	setSelectedDate: function(ADate) {
		if (typeof(ADate) == 'string')
			ADate = this.stringToDate(ADate);
		if (ADate)
			this.selectedDate = ADate;	
// TODO: if visible => update		
	}
});