/**
 * Calendar singleton class
 */

/**
 * Constructor
 */
var Calendar = function() {

	// Display date ( this will be detected at first render, contains only year and month, 200601 )
	this.renderDate 	= null;

	// Selected date ( this will be detected at first render, 20061201 )
	this.selectedDate   = null;

	// Language (two letters, in lowercase, defaults to lt)
	this.lang = 'lt';

	// Image url
	this.imageUrl = '';
	
	// Day names...
	this.dayNames = {
		lt : ['P', 'A', 'T', 'K', 'P', 'Š', 'S'],
		en : ['M', 'T', 'W', 'T', 'F', 'S', 'S'],
		ru : ['П', 'B', 'C', 'Ч', 'П', 'C', 'B']
	};

	// Month name
	this.monthNames = {
		lt :  ['Sausis', 'Vasaris', 'Kovas', 'Balandis', 'Gegužė', 'Birželis', 'Liepa', 'Rugpjūtis', 'Rugsėjis', 'Spalis', 'Lapkritis', 'Gruodis'],
		en : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
		ru : ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']

	};

	// Day events...
	this.dayEvents = {};
	
	
	// Where to output calendar data
	this.calendarElementId = false;

	// Select event handler 
	this.onSelected = null;
	

}

/**
 * Static - instance
 */
Calendar.instance = null;

/**
 * Static - get instance
 */
Calendar.getInstance = function() {
	return Calendar.instance ? Calendar.instance : ( Calendar.instance = new Calendar() );
}

/**
 * Static - get specific year month's day count
 */
Calendar.getMonthDayCount = function( year, month )  {

	var days = [31, ( ( ( year % 4 == 0 ) && ( year % 100 != 0 ) ) || ( year % 400 ) == 0 ) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

	return ( days[month - 1] ) ? days[month - 1] : days[0];

}

/**
 * Set month by delta, suported deltas +1 and -1
 */
Calendar.prototype.setMonth = function( delta ) {

	this.renderDate += delta;

	if( ( this.renderDate % 100 ) > 12 ) {
		this.renderDate = ( Math.floor( this.renderDate / 100 ) + 1 ) * 100 + 1;
	}

	if( ( this.renderDate % 100 ) < 1 ) {
		this.renderDate = ( Math.floor( this.renderDate / 100 ) - 1 ) * 100 + 12;
	}

	this.render();

}
/**
 * Get render date info by month delta
 */
Calendar.prototype.getDate = function( delta ) {

	var month = (this.renderDate % 100) + delta;
	var year = Math.floor(this.renderDate / 100);

	if ( month > 12 ) {
		month = month % 12;
		year++;
	}
	else if ( month < 1 ) {
		month = 12 + (month);
		year--;
	}
	
	//alert( 'year: ' + year + '\nmonth: ' + month );

	return { 'month': month, 'year': year };
}


/**
 * Set year by delta,
 */
 
Calendar.prototype.setYear = function( delta ) {

	this.renderDate = parseInt(( Math.floor( this.renderDate / 100 ) + delta ) + '' + Math.floor( this.renderDate % 100 ));

	this.render();
}


Calendar.prototype.onDayOver = function( element ) {
	element.className += ' week_over';
}

Calendar.prototype.onDayOut = function( element ) {
	element.className = element.className.replace( 'week_over', '' );
}

Calendar.prototype.setSelectedDate = function( fdate, tdate ) {
	this.selectedDate = fdate;
	this.selectedDateTo = tdate;
	
	var fyear = Math.floor( fdate / 10000 );
	var fmonth = Math.floor((fdate - fyear * 10000) / 100);
	var tyear = Math.floor( tdate / 10000 );
	var tmonth = Math.floor((tdate - tyear * 10000) / 100);
	var tday = tdate - tyear * 10000 - tmonth * 100;
	var days = [31, ( ( ( tyear % 4 == 0 ) && ( tyear % 100 != 0 ) ) || ( tyear % 400 ) == 0 ) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
	var mdays = ( days[tmonth - 1] ) ? days[tmonth - 1] : days[0];
	
	if ( tday > mdays && tyear == fyear && tmonth == fmonth ) {
		if ( tmonth < 10 ) {
			var tmonth = '0' + tmonth;
		}
		tdate = tyear + tmonth + mdays;
		this.selectedDateTo = tdate;
	}

	if (this.onSelected != null) {
		this.onSelected( this.toDateString(this.selectedDate), this.toDateString(this.selectedDateTo) );	
	}
	
	this.render();
}

Calendar.prototype.toDateString = function(date) {

	var year = Math.floor( date / 10000 );
	var month = Math.floor((date - year * 10000) / 100);	
	var day = date - year * 10000 - month * 100;

	return year + "-" + month + "-" + day;
}

/**
 * Render calendar
 */
Calendar.prototype.render = function() {
	
	
	// Define render date
	if( this.renderDate == null ) {
		this.renderDate = Math.floor( this.selectedDate / 100 );
	}
	
	var renderYear = Math.floor( this.renderDate / 100 );
	var renderMonth = this.renderDate % 100;

	// Create render date and set to render month and year
	var tempDate = new Date();
	tempDate.setYear( renderYear );
	tempDate.setDate( 1 );
	tempDate.setMonth( renderMonth - 1 );
	// Days count in current month
	var dayCount 			= Calendar.getMonthDayCount( renderYear, renderMonth );
	var prevDayCount 		= Calendar.getMonthDayCount( renderYear, renderMonth - 1 );
	
	// Get begin empty count, fixate for 0 = Sunday
	var beginEmptyCount 	= ( tempDate.getDay() + 6 ) % 7;
	var beginEmptyStart 	= prevDayCount - (beginEmptyCount - 1);
	
	// Cell htmls
	var cellHhtmls = [];

	// Render top row...
	for( var i = 0; i < this.dayNames[this.lang].length; i++ ) {
		if ( i==6 || i==5 ) {
			cellHhtmls.push( '<td class="cal_day_hdr cal_day_free">' + this.dayNames[this.lang][i] + '</td>' );
		} else {
			cellHhtmls.push( '<td class="cal_day_hdr">' + this.dayNames[this.lang][i] + '</td>' );
		}
	}

	// Render begin empty
	j = 1;
	/*for( var i = beginEmptyStart; i <= prevDayCount; i++ ) {
		if ( j > 5 ) {
			cellHhtmls.push( '<td class="cal_day_empty_free">'+i+'</td>' );
		} else {
			cellHhtmls.push( '<td class="cal_day_empty">'+i+'</td>' );
		}
		j++;
	}*/

	var weeks = new Array();
	
	// Render days
	var free = 1;
	for( var i = beginEmptyStart; i <= prevDayCount; i++ ) {

		var dayHasEvent = null;
		
		var monthDate	= this.renderDate - 1;
		var dayDate 	= monthDate * 100 + i;
		
		if( this.dayEvents[dayDate] ) {
			
			var dayTo = 7 - beginEmptyCount;
			var dayFrom = beginEmptyStart;

			var dayDateFrom = monthDate * 100 + dayFrom;

			var dayDateTo = this.renderDate * 100 + dayTo;

			dayHasEvent = 1;
			weekActionsHtml = ' onmouseover="Calendar.getInstance().onDayOver( this );" onmouseout="Calendar.getInstance().onDayOut( this );"  onclick="Calendar.getInstance().setSelectedDate( ' + dayDateFrom.toString() + ', ' + dayDateTo.toString() + ');"';
			
			weeks[1] = weekActionsHtml;
			
		}
		cellHhtmls.push( '<td class="cal_day_empty' + ( free == 6 ? '_free' : '' ) + ( dayHasEvent ? ' cal_day_marked' : '' ) + '">' + i + '</td>' );
		free++;
	}
	
	// Render days
	for( var i = 1; i <= dayCount; i++ ) {
			
		var currDate = new Date();
			currDate.setYear( renderYear );
			currDate.setMonth( renderMonth - 1 );
			currDate.setDate( i );
			
		var weekNo = Math.ceil( (beginEmptyCount + i) / 7 );
		var currWeekDay = currDate.getDay();		
		var firstWeekDays = 7 - beginEmptyCount;
		var dayHasEvent = null;
		
		var dayDate 	= this.renderDate * 100 + i;
		
		if( this.dayEvents[dayDate] ) {
			
			if ( weekNo == 1 ) {
				var dayTo = firstWeekDays;
				var dayFrom = 1;
			} else {
				var dayTo = firstWeekDays + ( (weekNo - 1) * 7 );
				var dayFrom = dayTo - 6;
				if ( dayTo > dayCount ) dayTo = dayCount;
			}
			var dayDateFrom = this.renderDate * 100 + dayFrom;
			var dayDateTo = this.renderDate * 100 + dayTo;

			dayHasEvent = 1;
			weekActionsHtml = ' onmouseover="Calendar.getInstance().onDayOver( this );" onmouseout="Calendar.getInstance().onDayOut( this );"  onclick="Calendar.getInstance().setSelectedDate( ' + dayDateFrom.toString() + ', ' + dayDateTo.toString() + ');"';
			
			if ( !weeks[weekNo] ) {
				weeks[weekNo] = weekActionsHtml;
			}
			
		}
		cellHhtmls.push( '<td class="' + ( dayHasEvent ? ' cal_day_marked' : '' ) + ( currWeekDay == 6 ? ' cal_day_free' : ( currWeekDay == 0 ? ' cal_day_free' : '' ) ) + '">' + i + '</td>' );
		
		if ( currWeekDay == 1 ) {
			var last_m_day = i;
		}
		
	}

	// Render end empty
	var cellsLeft = 49 - cellHhtmls.length;
	
	if ( 49 - cellHhtmls.length >= 7 ) {
		cellsLeft -= 7;
	}
	
	
	cLeft = cellsLeft;
	for( var i = 1; i <= cellsLeft; i++ ) {

		var dayHasEvent = null;
		
		var monthDate	= this.renderDate + 1;
		var dayDate 	= monthDate * 100 + i;
		
		if( this.dayEvents[dayDate] ) {
			
			var dayTo = 7 - beginEmptyCount;
			var dayFrom = beginEmptyStart;

			var dayDateFrom = this.renderDate * 100 + last_m_day;
			var dayDateTo = monthDate * 100 + cellsLeft;

			dayHasEvent = 1;
			weekActionsHtml = ' onmouseover="Calendar.getInstance().onDayOver( this );" onmouseout="Calendar.getInstance().onDayOut( this );"  onclick="Calendar.getInstance().setSelectedDate( ' + dayDateFrom.toString() + ', ' + dayDateTo.toString() + ');"';
			
			weeks[weekNo] = weekActionsHtml;
			
		}
		cellHhtmls.push( '<td class="cal_day_empty' + ( cLeft <= 2 ? '_free' : '' ) + ( dayHasEvent ? ' cal_day_marked' : '' ) + '">' + i + '</td>' );
		cLeft--;
	}
	
	var html = '<div class="calendar_border">';
	html += '<div class="calendar">';

	html += '<table class="cal_nav wf"><tr>';
	html += '<td class="cal_arrow cal_arrow_left"><a href="#" onclick="' + "showContent( 'year=' + Calendar.getInstance().getDate( -1 ).year + '&month=' + Calendar.getInstance().getDate( -1 ).month + '&curr_date=' + CurrentDate, 'calendar', 'calendar_block' ); return false;" + '"></a></td>';
	html += '<td class="year_month">' + renderYear.toString() + ' ' + this.monthNames[this.lang][renderMonth - 1] + '</td>';
	html += '<td class="cal_arrow cal_arrow_right"><a href="#" onclick="' + "showContent( 'year=' + Calendar.getInstance().getDate( 1 ).year + '&month=' + Calendar.getInstance().getDate( 1 ).month + '&curr_date=' + CurrentDate, 'calendar', 'calendar_block' ); return false;" + '"></a></td>';
	html += '</tr></table>';

	html += '<table class="cal_days">';
	var row = 0;
	
	//html += '<tr class="white">';

	// Now render all the stuff
	/*var i = 0;
	var last = false;
	if ( cellHhtmls.length % 7 == 0 ) {
		last = cellHhtmls.length / 7 -1;
	} else {
		last = Math.floor( cellHhtmls.length / 7 ) ;
	}*/
	while( cellHhtmls.length > 0 ) {
//		i++;
		// Add all cells
		html += cellHhtmls.slice( 0, 7 ).join( '' ) + '</tr>';
		
		// Splice up cells
		cellHhtmls = cellHhtmls.slice( 7 );

		if ( cellHhtmls.length > 0 ) {
		
			if ( row % 2 == 1 ) {
				html += '<tr class="white';
			} else {
				html += '<tr class="';
			}
		/*
			if ( i  == last ) {
				html += '<tr class="last';
			} else {
				html += '<tr class="';
			}
		*/	
			month = this.getDate(CurrentDate).month;

			
			
			week = row+1;
			
			if ( weeks[week] && week == WeekNumber ) {
				var month = Math.floor( CurrentDate / 100 );
				var month = month % 100;
				if ( month == renderMonth ) {
					html += ' cal_week_current';
				}
			}
			
			html += '"';
			if ( weeks[week] ) {
				html += weeks[week];
			}
			
			html += '>';
		}
		
		// Increase row
		row++;
	}

	html += '</table></div></div>';
	try { 
		$( this.calendarElementId ).innerHTML = html;
	} catch( error ) {
		// Failed to render
	}
	
}

Array.prototype.in_array = function(p_val) {
	for(var i = 0, l = this.length; i < l; i++) {
		if(this[i] == p_val) {
			return true;
		}
	}
	return false;
}