(function($) {
	$.fn.jCal = function (opt) {
		$.jCal(this, opt);
	}
	$.jCal = function (target, opt) {
		opt = $.extend({
			day:			new Date(),
			days:			1,
			showMonths:		1,
			sDate:			new Date(),
			eDate:			new Date(),
			dCheck:			function (day) { return true; },
			callback:		function (day, days) { return true; },
			selectedBG:		'',
			defaultBG:		'',
			_target:		target
		}, opt);
		opt.day.setDate(1);
		$(target).stop().empty();
		for (var sm=0; sm < opt.showMonths; sm++)
			$(target).append('<div class="jCalMo"></div>');
		opt.cID = 'c' + $('.jCalMo').length;
		$(target).find('.jCalMo').each(
			function (ind) {
				drawCal($(this), $.extend( {}, opt, { 'ind':ind, 
						'day':new Date( new Date( opt.day.getTime() ).setMonth( new Date( opt.day.getTime() ).getMonth() + ind ) ) }
					));
			}
		);
	}
	function drawCal (target, opt) {
//        $(target).append('<div class="ююю">');
//        $(target).prepend('<div class="ююю">');
        for (var ds in opt.dow)
            $(target).append('<div class="dow">' + opt.dow[ds] + '</div>');
//        $(target).append('</div>');
//		for (var ds in opt.dow)
//			$(target).append('<div class="dow">' + opt.dow[ds] + '</div>');

		// Future days
		var fd = new Date( new Date( opt.day.getTime() ).setDate(1) );
		// 
		var ldlm = new Date( new Date( fd.getTime() ).setDate(0) );
		// Last days
		var ld = new Date( new Date( new Date( fd.getTime() ).setMonth( fd.getMonth() + 1 ) ).setDate(0) );

		// ----------------------------------------------------------
		// alert(fd.getDay() +'+'+ ld.getDate()  +'+'+ ( 7 - ld.getDay() )+' '+ld.getDay());
		// fix by Dimon: in orignal version first-week day is Sunday
		// fix function is a _getDay( day )
		// ----------------------------------------------------------

		fdd = _getDay( fd.getDay() );

		// ------------ Code for testings ---------
/*		for (var d=1; d < ( fdd + ld.getDate() + ( 7 - _getDay( ld.getDay() ) ) ); d++)
		{
			if (d <= fdd )
			{
				// Past days
				str = '<div id="' + opt.cID + 'd' + d + '" class="pday">' + ( ldlm.getDate() - ( fdd - d ) ) + '</div>';
			}
			else if (d > ( fdd + ld.getDate()))
			{
				// Next days
				str = '<div id="' + opt.cID + 'd' + d + '" class="aday">' + ( d - ( fdd + ld.getDate() ) ) + '</div>';
			}
			else
			{
				// Current days
				str = '<div id="' + opt.cID + 'd_' + (fd.getMonth() + 1) + '_' + ( d - fdd ) + '_' + fd.getFullYear() + '" class="' +
					( ( opt.dCheck( new Date( (new Date( fd.getTime() )).setDate( d - fdd ) ) ) ) ? 'day' : 'invday' ) +
					'">' + ( d - fdd )  + '</div>';
			}
			$(target).append(str);
		}*/
		// ----------------------------------------------------------

		// ---------------  fixed Code ------------
		for (var d=1; d < ( fdd + ld.getDate() + ( 7 - _getDay( ld.getDay() ) ) ); d++)
			$(target).append(
				(( d <= fdd ) ? 
					'<div id="' + opt.cID + 'd_' + (ld.getMonth()) + '_' + ( ldlm.getDate() - ( fdd - d ) ) + '_' + ld.getFullYear() + '" class="pday">' + ( ldlm.getDate() - ( fdd - d ) ) + '</div>' 
					: ( ( d > ( fdd + ld.getDate() ) ) ?
						'<div id="' + opt.cID + 'd' + d + '" class="aday">' + ( d - ( fdd + ld.getDate() ) ) + '</div>' 
						: '<div id="' + opt.cID + 'd_' + (fd.getMonth() + 1) + '_' + ( d - fdd ) + '_' + fd.getFullYear() + '" class="' +
							( ( opt.dCheck( new Date( (new Date( fd.getTime() )).setDate( d - fdd ) ) ) ) ? 'day' : 'invday' ) +
							'">' + ( d - fdd )  + '</div>'
					) 
				)
			);
		// ----------------------------------------------------------

		// ----------- Orginal code ----------
/*		for (var d=1; d < ( fd.getDay() + ld.getDate() + ( 7 - ld.getDay() ) ); d++)
			$(target).append(
				(( d <= fd.getDay() ) ? 
					'<div id="' + opt.cID + 'd' + d + '" class="pday">' + ( ldlm.getDate() - ( fd.getDay() - d ) ) + '</div>' 
					: ( ( d > ( fd.getDay() + ld.getDate() ) ) ?
						'<div id="' + opt.cID + 'd' + d + '" class="aday">' + ( d - ( fd.getDay() + ld.getDate() ) ) + '</div>' 
						: '<div id="' + opt.cID + 'd_' + (fd.getMonth() + 1) + '_' + ( d - fd.getDay() ) + '_' + fd.getFullYear() + '" class="' +
							( ( opt.dCheck( new Date( (new Date( fd.getTime() )).setDate( d - fd.getDay() ) ) ) ) ? 'day' : 'invday' ) +
							'">' + ( d - fd.getDay() )  + '</div>'
					) 
				)
			);*/
		// ----------------------------------------------------------

		$(target).find('div[id^=' + opt.cID + 'd]:first, div[id^=' + opt.cID + 'd]:nth-child(7n+1)').before( '<br style="clear:both; font-size:0.1em;" />' );
		$(target).prepend( '<div class="jCal ' + ( (opt.ind == 0) ? 'al_center"' :
					( (opt.ind == ( opt.showMonths - 1 )) ? 'al_right"' : '' ) ) + '">' +
//				'<div class="jCal">' +
//					( (opt.ind == 0) ? '<span class="left"><img src="'+baseurl+'/images/_left.gif"></span>' : '' ) + 
					( (opt.ind == 0) ? '<span class="left">&#160;</span>' : '' ) +
					'<span class="month">' + opt.ml[opt.day.getMonth()] + ' ' + opt.day.getFullYear() + '</span>' +
//					( (opt.ind == ( opt.showMonths - 1 )) ? '<span class="right"><img src="'+baseurl+'/images/_right.gif"></span>' : '' ) +
					( (opt.ind == ( opt.showMonths - 1 )) ? '<span class="right">&#160;</span>' : '' ) +
//				'</div>' +
			'</div>');
		$(target).find('.jCal .left').bind("click", function (e) {
				opt.day.setMonth( opt.day.getMonth() - 1);
				$.jCal($(target).parent(), opt);
			});
		$(target).find('.jCal .right').bind("click", function (e) {
				opt.day.setMonth( opt.day.getMonth() + ( (opt.showMonths == 1) ? 1 : 0 ) );
				$.jCal($(target).parent(), opt);
			});
		// Org.code:  $(target).find('div[id^=' + opt.cID + 'd_]:not(.invday)').bind("mouseover mouseout click", function(e){
		$(target).find('div[id^=' + opt.cID + 'd_]').bind("mouseover mouseout click", function(e){
			var osDate = new Date ( $(this).attr('id').replace(/c[0-9]{1,}d_([0-9]{1,2})_([0-9]{1,2})_([0-9]{4})/, '$1/$2/$3') );
			var sDate = new Date ( osDate.getTime() );
			if (e.type == 'click') 
				$('div[id^=' + opt.cID + 'd_].selectedDay', $(opt._target).parent()).removeClass('selectedDay').animate(
					{ background:opt.defaultBG }, 'fast', function () {
						//$(this).css('background', '');
					});
			for (var di=0; di < opt.days; di++) {
				var currDay = $(opt._target).find('#' + opt.cID + 'd_' + ( sDate.getMonth() + 1 ) + '_' + sDate.getDate() + '_' + sDate.getFullYear());
				if ( currDay == null || $(currDay).hasClass('invday') ) break;
				$(currDay).toggleClass( ( (e.type == 'click') ? 'selectedDay' : 'overDay' ) );
				if (e.type == 'click') $(currDay).stop().animate({ background:opt.selectedBG }, 'fast', function () {
					//$(this).css('background', opt.selectedBG);
				});
				//else $(currDay).css('background', '').stop();
				sDate.setDate( sDate.getDate() + 1 );
			}
			if (e.type == 'click') opt.callback( osDate, di );
		});
	}
})(jQuery);

function _getDay(day)
{
	if (day > 0) return day-1;
	if (!day) return 6;
}
