var monthDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
var actualMonth = new Date().getMonth();
var actualYear = new Date().getFullYear();

//use this function to gets number of days per month, it handles leap years
function getDaysPerMonth(month, year) {
	if(month < 0 || month > 11) {
		month = 0;
	}

	var days = monthDays[month];
	if(month == 1) {
		if((year % 4) == 0) {
			if(((year % 100) == 0) && (year % 400) != 0)
				days = 28;
			else
				days = 29;
		}
	}
	return days;
}

function preparePreviousMonth() {
	if(actualMonth > 0) {
		actualMonth -= 1;
	}
	else {
		actualMonth = 11;
		actualYear--;
	}
}

function prepareNextMonth() {
	if(actualMonth < 11) {
		actualMonth += 1;
	}
	else {
		actualMonth = 0;
		actualYear++;
	}
}

function showCalendar(useEnFormat, containerClass, containerId) {
	document.write(buildCalendar(actualMonth, actualYear, useEnFormat, containerClass, containerId));
	bindCalendarAnchors(containerId);
}

function bindCalendarAnchors(containerId) {
	$("#frmSelectedDays").attr("value", "");
	$("#frmSelectedMonth").attr("value", actualMonth+1);
	$("#frmSelectedYear").attr("value", actualYear);
	$("#"+containerId+" td a").bind("click", function(event) {
		$(this).toggleClass("selected");
		var selectedDays = new StringBuffer();
		$("#"+containerId+" td a").each(function() {
			if ($(this).hasClass("selected")) {
				selectedDays.append($(this).text()).append(';');
			}
		});
		$("#frmSelectedDays").attr("value", selectedDays.getString().substring(0, selectedDays.getString().length-1));
		event.preventDefault();
	});
}

//Main calendar function
// uses dayNames/monthNames defined in /lang/local.js
function buildCalendar(month, year, useEnFormat, containerClass, containerId) {
	var beginDate = new Date(year, month, 1);
	var decorator = new CalendarDecorator();
    var output = new StringBuffer();
	output.append('<div class="').append(containerClass).append('" id="').append(containerId).append('">');
	decorator.printCalendarBegin(output);
	writeDays(dayNames, decorator, output, useEnFormat);
	writeWeeks(beginDate, decorator, output, useEnFormat);
	decorator.printCalendarEnd(output);

	var monthNavi = new StringBuffer();
	monthNavi.append('<p class="month-navi"><a class="prev" href="#" onclick="return writePrevMonth(\'').append(containerId).append('\')">').append(locale["prev"]).append('</a>');
	monthNavi.append('<span> | </span><strong><em>').append(monthNames[actualMonth]).append('</em> ').append(actualYear).append('</strong><span> | </span>');
	monthNavi.append('<a class="next" href="#" onclick="return writeNextMonth(\'').append(containerId).append('\')">').append(locale["next"]).append('</a></p>');
	monthNavi.append('<p class="month-navi-add clear clr">\n');
	monthNavi.append('	<a class="whole-month" href="#" onclick="return selectWholeMonth(\'').append(containerId).append('\')">').append(locale["whole-month-select"]).append('</a>');
	monthNavi.append('	<a class="cancel-selected" href="#" onclick="return cancelSelectedDays(\'').append(containerId).append('\')">').append(locale["cancel-selected"]).append('</a>');
	monthNavi.append('</p>\n');
	output.append(monthNavi.getString());


	output.append('</div>');

	return output.getString();
}

function writePrevMonth(containerId) {
	var trueActualMonth = new Date().getMonth();
	var trueActualYear = new Date().getFullYear();
	if (actualYear <= trueActualYear && actualMonth <= trueActualMonth) return false;
	preparePreviousMonth();
	var calClass = $("#"+containerId).attr("class");
	$("#"+containerId).replaceWith(buildCalendar(actualMonth, actualYear, false, calClass, containerId));
	bindCalendarAnchors(containerId);
	return false;
}

function writeNextMonth(containerId) {
	prepareNextMonth();
	var calClass = $("#"+containerId).attr("class");
	$("#"+containerId).replaceWith(buildCalendar(actualMonth, actualYear, false, calClass, containerId));
	bindCalendarAnchors(containerId);
	return false;
}

function selectWholeMonth(containerId) {
	$("#"+containerId + " td a").addClass("selected");
	var selectedDays = new StringBuffer();
	$("#"+containerId+" td a").each(function() {
		selectedDays.append($(this).text()).append(';');
	});
	$("#frmSelectedDays").attr("value", selectedDays.getString().substring(0, selectedDays.getString().length-1));
	return false;
}

function cancelSelectedDays(containerId) {
	$("#"+containerId + " td a").removeClass("selected");
	$("#frmSelectedDays").attr("value", "");
	return false;
}

//day starts with zero, sunday is last, i.e. equals 6
function normalizeDayInWeek(day) {
	if(day > 0) {
		return day;
	}
	else {
		return 7;
	}
}

//writes table header
function writeDays(dayNames, decorator, output, useEnFormat) {
	decorator.printWeekBegin(output);
	var index;
	for(var i = 0; i < 7; i++) {
		if(useEnFormat) {
			if(i > 0) {
				index = i - 1;
			}
			else {
				index = 6;
			}
		}
		else {
			index = i;
		}

		decorator.printDayHeader(output, dayNames[index]);
	}
	decorator.printWeekEnd(output);
}

//writes calendar days
function writeWeeks(beginDate, decorator, output, useEnFormat) {
	var enFormatHelper = 0;
	if(useEnFormat) {
		enFormatHelper = 1;
	}

	var actualDate = new Date();

	decorator.printWeekBegin(output);

	//number of days of previous month to fill
	var previousRemainingDays = normalizeDayInWeek(beginDate.getDay()) - 1 + enFormatHelper;
	if(previousRemainingDays > 0) {
		var previousMonthDays;
		if(beginDate.getMonth() == 0) {
			previousMonthDays = getDaysPerMonth(11, beginDate.getFullYear() - 1);
		}
		else {
			previousMonthDays = getDaysPerMonth(beginDate.getMonth() - 1, beginDate.getFullYear());
		}

		for(var i = previousRemainingDays - 1; i >= 0; i--) {
			decorator.printPreviousMonthDay(output, previousMonthDays - i);
		}
	}

	//get number of days of actual generated month
	var actualMonthDays = getDaysPerMonth(beginDate.getMonth(), beginDate.getFullYear());

	//count number of days not filled in first week
	var remainingDays = 7 - previousRemainingDays;

	//fill days of actual month
	for(i = 1; i <= actualMonthDays; i++) {
		if(remainingDays == 7 && i > 1) {
			decorator.printWeekBegin(output);
		}
		decorator.printDay(output, i, isActualDay(actualDate, beginDate, i));
		
		remainingDays--;
		if(remainingDays == 0) {
			decorator.printWeekEnd(output);
			remainingDays = 7;
		}
	}

	//not all days in last week were filled, fill days of next week
	if(remainingDays > 0 && remainingDays < 7) {
	    for(i = 1; i <= remainingDays; i++) {
			decorator.printNextMonthDay(output, i);
		}
		decorator.printWeekEnd(output);
	}
}

function isActualDay(actualDate, testedDate, testedDayOfMonth) {
	return testedDate.getMonth() == actualDate.getMonth() && testedDate.getYear() == actualDate.getYear() && testedDayOfMonth == actualDate.getDate();
}

function CalendarDecorator() {
	this.printCalendarBegin = function(output) {
		output.append('<table>\n');
	};

	this.printCalendarEnd = function(output) {
		output.append('</table>\n');
	};


	this.printWeekBegin = function(output, clazz) {
		if(clazz) {
			output.append('<tr class="').append(clazz).append('">\n');
		}
		else {
			output.append('<tr>');
		}
	};

	this.printWeekEnd = function(output) {
		output.append('</tr>\n');
	};

	this.printDayHeader = function(output, dayName) {
		output.append('<th>').append(dayName).append('</th>\n');
	};

	this.printDay = function(output, dayNumber, isActual) {
		if(isActual) {
			output.append('<td><a href="#"><strong>').append(dayNumber).append('</strong></a></td>\n');
		}
		else {
			output.append('<td><a href="#">').append(dayNumber).append('</a></td>\n');
		}
	};

	this.printPreviousMonthDay = function(output, dayNumber) {
		output.append('<td class="previous"><em>').append(dayNumber).append('</em></td>\n');
	};

	this.printNextMonthDay = function(output, dayNumber) {
		output.append('<td class="next"><em>').append(dayNumber).append('</em></td>\n');
	};
}
/* obsluha formu */
function calendarHiddenInputs(str) {
	var output = new StringBuffer();
	if (str.indexOf("D") > -1) {
		output.append('<input type="hidden" name="days" id="frmSelectedDays" value="" />\n');
	}
	if (str.indexOf("M") > -1) {
		output.append('<input type="hidden" name="month" id="frmSelectedMonth" value="" />\n');
	}
	if (str.indexOf("Y") > -1) {
		output.append('<input type="hidden" name="year" id="frmSelectedYear" value="" />\n');
	}

	return output.getString();
}

