jQuery.fn.calendarPicker = function(options) {
	if (!options.date) options.date = new Date();

	if (typeof(options.years)			== 'undefined')	options.years = 1;
	if (typeof(options.months)			== 'undefined')	options.months = 3;
	if (typeof(options.days)			== 'undefined')	options.days = 4;
	if (typeof(options.showDayArrows)	== 'undefined')	options.showDayArrows = true;
	if (typeof(options.useWheel)		== 'undefined')	options.useWheel = false;
	if (typeof(options.callbackDelay)	== 'undefined')	options.callbackDelay = 500;
	if (typeof(options.monthNames)		== 'undefined')	options.monthNames = ['gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic'];
	if (typeof(options.dayNames)		== 'undefined')	options.dayNames = ['dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab'];
	
	var calendar = {currentDate: options.date};
	calendar.options = options;
	
	// build the calendar on the first element in the set of matched elements.
	var theDiv = this.eq(0); // $(this);
	theDiv.addClass('calBox');
	
	theDiv.empty();
	
	var divYears	= $('<div>').addClass('calYear');
	var divMonths	= $('<div>').addClass('calMonth');
	var divDays		= $('<div>').addClass('calDay');
	
	calendar.changeDate = function(date) {
		calendar.currentDate = date;
		
		var fillYears = function(date) {
			if (options.years) {
				theDiv.append(divYears);
				var year = date.getFullYear();
				var t = new Date();
				divYears.empty();
				var nc = options.years * 2 + 1;
				var w = parseInt((theDiv.width() - 4 - nc * 4) / nc) + 'px';
				for (var i = year - options.years; i <= year + options.years; i++) {
					var d = new Date(date);
					d.setFullYear(i);
					var span = $('<span>').addClass('calElement').attr('millis', d.getTime()).html(i).css('width', w);
					if (d.getYear() == t.getYear())
						span.addClass('today');
					if (d.getYear() == calendar.currentDate.getYear())
						span.addClass('selected');
					divYears.append(span);
				}
			}
		};
		
		var fillMonths = function(date) {
			if (options.months) {
				theDiv.append(divMonths);
				var month = date.getMonth();
				var t = new Date();
				divMonths.empty();
				var oldday = date.getDay();
				var nc = options.months * 2 + 1;
				var w = parseInt((theDiv.width() - 4 - nc * 4) / nc) + 'px';
				for (var i = -options.months; i <= options.months; i++) {
					var d = new Date(date);
					var oldday = d.getDate();
					d.setMonth(month + i);
					if (d.getDate() != oldday) {
						d.setMonth(d.getMonth() - 1);
						d.setDate(28);
					}
					var span = $('<span>').addClass('calElement').attr('millis', d.getTime()).html(options.monthNames[d.getMonth()]).css('width', w);
					if (d.getYear() == t.getYear() && d.getMonth() == t.getMonth())
						span.addClass('today');
					if (d.getYear() == calendar.currentDate.getYear() && d.getMonth() == calendar.currentDate.getMonth())
						span.addClass('selected');
					divMonths.append(span);
				}
			}
		};
		
		var fillDays = function(date) {
			theDiv.append(divDays);
			var day = date.getDate();
			
			// la settimana parte da luned́
			var dayToAdd = date.getDay();
			if (dayToAdd == 0) dayToAdd = 7;
			dayToAdd = 4 - dayToAdd;
			
			var t = new Date();
			divDays.empty();
			var nc = options.days * 2 + 1;
			var w = parseInt((theDiv.width() - 4 - (options.showDayArrows ? 12 : 0) - (nc) * 4) / (nc - (options.showDayArrows ? 2 : 0))) + 'px';
			for (var i = -options.days; i <= options.days; i++) {

				var d = new Date(date);
				d.setDate(day + i + dayToAdd);

				var span = $('<span>');
				if (i == 3) span.addClass('red');
				
				if (i == -options.days && options.showDayArrows) {
					span.addClass('calElement').attr('millis', d.getTime());
					span.addClass('prev');
				} else if (i == options.days && options.showDayArrows) {
					span.addClass('calElement').attr('millis', d.getTime());
					span.addClass('next');
				} else {
					span.addClass('calElement').attr('millis', d.getTime());
					span.html('<span class="dayNumber">' + d.getDate() + '</span><br />' + options.dayNames[d.getDay()]).css('width', w);
					if (d.getYear() == t.getYear() && d.getMonth() == t.getMonth() && d.getDate() == t.getDate())
						span.addClass('today');
					if (d.getYear() == calendar.currentDate.getYear() && d.getMonth() == calendar.currentDate.getMonth() && d.getDate() == calendar.currentDate.getDate())
						span.addClass('selected');
				}
				divDays.append(span);
			}
		};
		
		/*
		var deferredCallBack = function() {
			if (typeof(options.callback) == 'function') {
				if (calendar.timer) clearTimeout(calendar.timer);
				calendar.timer = setTimeout(function() {
					options.callback(calendar);
				}, options.callbackDelay);
			}
		};
		*/

		fillYears(date);
		fillMonths(date);
		fillDays(date);
		
		//deferredCallBack();
	};

	divMonths.click(function(ev) {
		var el = $(ev.target);
		var monthDate = new Date(parseInt(el.attr("millis")));
		monthDate.setDate(1);

		var dayToAdd = monthDate.getDay();		
		if (dayToAdd == 0) dayToAdd = 7;
		dayToAdd = 1 - dayToAdd;

		monthDate.setDate(monthDate.getDate() + dayToAdd);
		calendar.changeDate(monthDate);
	});
	
	divDays.click(function(ev) {
		var el = $(ev.target).closest('.calElement');
		if (el.hasClass('prev') || el.hasClass('next')) calendar.changeDate(new Date(parseInt(el.attr('millis'))));
		else {
			if (typeof(options.callback) == 'function') {
				var dayDate = new Date(parseInt(el.attr('millis')));
				if (dayDate.toString() != 'Invalid Date') options.callback(dayDate);
			}
		}
	});
	
	// mousewheel
	if ($.event.special.mousewheel && options.useWheel) {
		divYears.mousewheel(function(event, delta) {
			var d = new Date(calendar.currentDate.getTime());
			d.setFullYear(d.getFullYear() + delta);
			calendar.changeDate(d);
			return false;
		});
		
		divMonths.mousewheel(function(event, delta) {
			var d = new Date(calendar.currentDate.getTime());
			d.setMonth(d.getMonth() + delta);
			calendar.changeDate(d);
			return false;
		});
		
		divDays.mousewheel(function(event, delta) {
			var d = new Date(calendar.currentDate.getTime());
			d.setDate(d.getDate() + delta);
			calendar.changeDate(d);
			return false;
		});
	}
	
	calendar.changeDate(options.date);
	
	return calendar;
};
