$(function(){

$.fn.calendar = function(){
	$('input[date = true]').each(function(n, field){
		var f = $(field);
		var calendar = new $.calendar({
			minValue: Date.parse(f.attr('min')) ? Date.parse(f.attr('min')).clearTime() : (new Date).clearTime(),
			maxValue: Date.parse(f.attr('min')) ? Date.parse(f.attr('max')).clearTime() : (new Date).clearTime().addMonths(12),
			initial: Date.parse(f.val()) ? Date.parse(f.val()).clearTime() : (new Date).clearTime(),
			today: Date.parse(f.attr('today')) ? Date.parse(f.attr('today')).clearTime() : (new Date).clearTime(),
			icon: f.attr('datepicker'),
			static: f.attr('static') == 'true',
			field: f,
			disabled: f.attr('disabled')
		});
	});
}

$.calendar = function(config){

	var icons = {
		'default': new Image(),
		'disabled': new Image(),
		'selected': new Image()
	}

	if (config.icon == 'blue'){
		icons['default'].src = 'http://agent.ru/media/img/calendar/calendar.gif';
		icons['disabled'].src = 'http://agent.ru/media/img/calendar/calendar-disabled.gif';
		icons['selected'].src = 'http://agent.ru/media/img/calendar/calendar-selected.gif';
	} else {
		icons['default'].src = 'http://agent.ru/media/img/calendar/calendar-white.gif';
		icons['disabled'].src = 'http://agent.ru/media/img/calendar/calendar-disabled-white.gif';
		icons['selected'].src = 'http://agent.ru/media/img/calendar/calendar-selected-white.gif';
	}

	var calDIV;
	if (config.static){
		calDIV = $('<div class="calendar calendar-static"/>').insertAfter(config.field);
	} else {
		calDIV = $('<div class="calendar"/>').appendTo($('body'));
	}

	var calLAYOUT = $('<div class="calendarLayout"/>').appendTo(calDIV);
	var calHEADER = $('<div class="calendarHeader"/>').appendTo(calLAYOUT);
	var calMonthLeft = $('<div class="calendarMonthLeft"/>').appendTo(calHEADER);
	var calMonthRight = $('<div class="calendarMonthRight"/>').appendTo(calHEADER);
	var calPrevMONTH = $('<div class="calendarPrevMonth"/>').appendTo(calHEADER);
	var calNextMONTH = $('<div class="calendarNextMonth"/>').appendTo(calHEADER);
	var calPrevMONTHarrow = $('<img src="http://agent.ru/media/img/calendar/back.gif"/>').appendTo(calPrevMONTH);
	var calNextMONTHarrow = $('<img src="http://agent.ru/media/img/calendar/forward.gif"/>').appendTo(calNextMONTH);

	var calendar = {
		adjustPosition: function(){
			if (!config.static){
				var obj = calendar.cfg.icon.parent().parent();
				calendar.cfg.obj.css('left', obj.offset().left);
				calendar.cfg.obj.css('top', obj.offset().top + calendar.cfg.icon.height());
			}
		},

		build: function(date, fireEvent, force){
			this.cfg.monthsDays[0].empty();
			this.cfg.monthsDays[1].empty();

			if (!date) this.currentMonth = false;

			var dateCurrent = this.cfg.today.clone();
			var dateSelected = this.getSelectedDate(Date.parse(this.cfg.field.val()));

			var date = (date) ? date : (dateSelected) ? dateSelected : dateCurrent;
			var tmpDate = date.clone(); tmpDate.setDate(1); tmpDate = tmpDate.addMonths(1);
//		var tmpDate2 = date.clone().add(Date.MONTH, -1);
			var tmpDateTo = date.clone(); tmpDateTo.setDate(tmpDateTo.getDaysInMonth());

			var minDate = this.cfg.minValue.clone(); minDate.setDate(1);
			var maxDate = this.cfg.maxValue.clone(); maxDate.setDate(maxDate.getDaysInMonth());

			if (tmpDate.getTime() < minDate.getTime() && this.cfg.minValue.getTime() < this.cfg.maxValue.getTime()){
				return this.build(this.cfg.minValue);
			}
			if (tmpDateTo.getTime() > maxDate.getTime()){
				return this.build(this.cfg.maxValue);
			}

			var left = date.clone();
			var right = tmpDate.clone();

			this.changeMonth(null, date.clone());

			if (!date) return;
	                                                             	
	// first calendar
			this.cfg.leftMonth.html(Date.CultureInfo.monthNames[date.getMonth()] + ', ' + date.getFullYear());
			this.getHTML(left, dateCurrent, dateSelected, this.cfg.monthsDays[0]);
	///first calendar
	
	
	// second calendar
			this.cfg.rightMonth.html(Date.CultureInfo.monthNames[tmpDate.getMonth()] + ', ' + tmpDate.getFullYear());
			this.getHTML(right, dateCurrent, dateSelected, this.cfg.monthsDays[1]);
	///second calendar

			if (!force && this.cfg.static && $(this.cfg.grid).find('span.active').length < 7){
				this.changeMonth('back', date.clone());
			}

			if (typeof fireEvent != 'string' && this.cfg.listeners && this.cfg.listeners.build){
				this.cfg.listeners.build();
			}

//			this.cfg.grid.clean();
		},
	
		getHTML: function(date, dateCurrent, dateSelected, el)
		{
			var date = date.clone();
			var startMonth = date.clone(); startMonth.setDate(1);
			var startDay = (startMonth.getDay() == 0) ? 7 : startMonth.getDay();
			var prevMonth = date.clone(); prevMonth.setDate(1); prevMonth = prevMonth.addMonths(-1); prevMonth.setDate(prevMonth.getDaysInMonth() - startDay + 2);
			var nextMonth = date.clone(); nextMonth.setDate(1); nextMonth = nextMonth.addMonths(1);
			this.drawDays(el, startMonth,startDay,prevMonth,nextMonth,dateCurrent,dateSelected,1);
			return false;
		},
	
		drawDays: function(el, startMonth, startDay, prevMonth, nextMonth, dateCurrent, dateSelected){
			var day = 1;
			var div = $('<div/>').appendTo(el);
			var HTML = '';

			var selectedWeek = dateSelected.clone().addDays(-1).getWeekOfYear();

			if (startDay != 1)
			{
				for (var i = prevMonth.getDate(); i < prevMonth.getDate() + startDay - 1; i++)
				{
					var span;
					if (this.cfg.static){
						span = $('<span class="spanHidden"/>').appendTo(div);
					}

					$('<a class="calendarHidden">' + i + '</a>').appendTo(span ? span : div);

					day++;
				}
			}
	
			for (var i = 1; i <= startMonth.getDaysInMonth(); i++)
			{
				if ( (day - 1) % 7 == 0 ) div = $('<div/>').appendTo(el);
	
				var tmpDate = startMonth.clone(); tmpDate.setDate(i);
				var disabled = (tmpDate.getTime() < this.cfg.minValue.getTime() || tmpDate.getTime() > this.cfg.maxValue.getTime());

				var cl = '';
				if (disabled){
					cl = 'calendarDisabled';
				} else {
					if (dateSelected.getTime() == tmpDate.getTime()) cl += 'calendarSelected ';
					if (tmpDate.getDay() == 6 || tmpDate.getDay() == 0) cl += 'calendarWeekend ';
				}

				if (dateCurrent.getTime() == tmpDate.getTime()) cl = (disabled) ? 'calendarCurrentDisabled' : 'calendarCurrent ';
				if (!disabled && dateSelected.getTime() == tmpDate.getTime()) cl += 'calendarSelected';

				var span;
				if (this.cfg.static){
					span = $('<span/>').appendTo(div);
					if (!disabled && tmpDate.clone().addDays(-1).getWeekOfYear() == selectedWeek){
						span.addClass('active');
					}
				}

				$('<a class="' + cl +
					'" date="' + i + '.' + (startMonth.getMonth() + 1) + '.' + startMonth.getFullYear() +
					'" href="#" onclick="return false;" onfocus="this.blur();">' +
					i +
					'</a>').appendTo(span ? span : div);

				day++;
			}
	
			if (i < 42)
			{
				for (var i = nextMonth.getDate(); day <= 42; i++)
				{
					if ( (day - 1) % 7 == 0) div = $('<div/>').appendTo(el);

					if (this.cfg.static){
						span = $('<span class="spanHidden"/>').appendTo(div);
					}

					$('<a class="calendarHidden">' + i + '</a>').appendTo(span ? span : div);

					day++;
				}
			}

			return false;
		},
	
		choose: function(value)
		{
			var value = this.parseDate(value);
			if (!value) return false;

			if (value.getTime() <= this.cfg.minValue.getTime()) {
				value = this.cfg.minValue;
			}
	
			if (value.getTime() >= this.cfg.maxValue.getTime())	{
				value = this.cfg.maxValue;
			}
	
			for (var i = 0; i < value.length; i++ )
			{
				if (value[i] < 10) value[i] = '0' + value[i];
			}
	
			this.cfg.field.val(value.toString('dd.MM.yyyy'));
			this.build(false, 'false');
			if (!this.cfg.static){
				this.hide(true);
			}
		},

		disable: function(){
			if (this.disabled) return;
			if (this.cfg.icon){
				this.cfg.icon.src = icons['disabled'].src;
				this.cfg.icon.className = 'calendarLinkDisabled';
			}
			this.disabled = true;
			this.cfg.obj.css('display', 'none');
		},

		enable: function(){
			if (!this.disabled) return;
			if (this.cfg.icon){
				this.cfg.icon.src = icons['default'].src;
				this.cfg.icon.className = 'calendarLink';
			}
			this.disabled = false;
		},

		show: function(){
			var obj = calendar.cfg.obj;
			if (obj.is(':visible') || this.processing) return;

			if (this.cfg.static) {
				obj.css('display', 'block');
			} else {
				this.processing = true;
				if (!obj.is(':animated')) this.adjustPosition();
				obj.stop();
				obj.css('z-index', '13000');

				obj.show('fast', function(){
					calendar.processing = false;
				});
			}

			this.build();

			if (this.cfg.icon){
				this.cfg.icon[0].src = icons['selected'].src;
			}
		},

		hide: function(force){
			var obj = this.cfg.obj;
			if (force){
				obj.css('display', 'none');
				if (this.cfg.icon){
					this.cfg.icon[0].src = this.disabled ? icons['disabled'].src : icons['default'].src;
				}
				return;
			}
			if (obj.is(':hidden') || this.processing) return;
			this.processing = true;

			if (!obj.is(':animated')) this.adjustPosition();
			obj.stop();
			obj.css('z-index', '12500');

			obj.hide('fast', function(){
				calendar.processing = false;
			});

			if (this.cfg.icon){
				this.cfg.icon[0].src = this.disabled ? icons['disabled'].src : icons['default'].src;
			}
		},

		toggle: function(){
			if (!this.disabled){
				if (this.cfg.obj.is(':visible')){
					this.hide();
				}	else {
					this.show();
				}
			}
		},
	
		getSelectedDate: function(date)
		{
			var date = 
			(this.parseDate(date)) ? this.parseDate(date) :
			(this.cfg.field.minValue) ? this.cfg.field.minValue :
			(this.cfg.field.val().length > 0 && this.parseDate(this.cfg.field.val())) ? this.parseDate(this.cfg.field.val()) :
			new Date();

			date.clearTime();
	
			return date;
		},

		parseDate: function(date)
		{
			if (date)
			{
				var re = /^\d{1,2}[.]\d{1,2}[.]\d{4}$/;
				if (typeof(date) == 'string' && date.match(re))
				{
					date = date.split('.');
					for (var i = 0; i < 2; i++)
					{
						date[i] = date[i].replace(/^0/,'');
					}
	
					date = new Date(parseInt(date[2]), parseInt(date[1] - 1), parseInt(date[0]));
					date.clearTime();
				} else if (typeof(date) == 'object') {
					date.clearTime();
				}
				else
				{
					date = false;
				}
			}
	
			return date;
		},

		changeMonth: function(direction, dateSelected)
		{
			if (!this.currentMonth){
				this.currentMonth = dateSelected;
				this.currentMonth.setDate(1);
			}

			var tmpDateFrom = this.currentMonth.clone();
			var tmpDateTo = this.currentMonth.clone();
			tmpDateTo = tmpDateTo.addMonths(1);
			tmpDateTo.setDate(tmpDateTo.getDaysInMonth());

			this.cfg.prevMonthArrow.css('visibility', (tmpDateFrom <= this.cfg.minValue) ? 'hidden' : 'inherit');
			this.cfg.nextMonthArrow.css('visibility', (tmpDateTo >= this.cfg.maxValue) ? 'hidden' : 'inherit');

			if (direction == 'back' && tmpDateFrom > this.cfg.minValue){
				this.currentMonth = this.currentMonth.addMonths(-1);
				this.build(this.currentMonth, null, true);
			} else if (direction == 'forward' && tmpDateTo < this.cfg.maxValue){
				this.currentMonth = this.currentMonth.addMonths(1);
				this.build(this.currentMonth, null, true);
			}

			return false;
		}
	}

	calendar.cfg = {
		animate: true,//config.animate,
		listeners: config['listeners'],
		field: config['field'],
		minValue: config['minValue'].clearTime(true),
		maxValue: config['maxValue'].clearTime(true),
		initial: config['minValue'].clearTime(true),
		today: config['today'].clearTime(),
		obj: calDIV,
		prevMonth: calPrevMONTH,
		nextMonth: calNextMONTH,
		prevMonthArrow: calPrevMONTHarrow,
		nextMonthArrow: calNextMONTHarrow,
		leftMonth: calMonthLeft,
		rightMonth: calMonthRight,
		static: config['static'],
		disabled: config['disabled'],
		icon: config['icon']
	}

	if (!config.static){
		var iconDIV = $('<div class="unit indent"/>').appendTo($(config.field).parent().parent().parent());
		calendar.cfg.icon = $('<img src="' + icons['default'].src + '" class="calendarLink"/>').appendTo(iconDIV);
	}

	function calendarInit(){
		calendar.cfg.grid = $('<div class="calendarCalendars"/>').appendTo(calLAYOUT);
		calendar.cfg.months = []

		calendar.cfg.months[0] = $('<div class="calendarFirst"><div class="calendarDayNames"><span></span></div></div>').appendTo(calendar.cfg.grid);
		calendar.cfg.months[0].find('span').append(calendar.dayNames);

		calendar.cfg.grid.append('<div class="calendarBorder"><div/></div>');

		calendar.cfg.months[1] = $('<div class="calendarSecond"><div class="calendarDayNames"><span></span></div></div>').appendTo(calendar.cfg.grid);
		calendar.cfg.months[1].find('span').append(calendar.dayNames);

		calendar.cfg.monthsDays = [
			$('<div class="calendarDays"/>').appendTo(calendar.cfg.months[0]),
			$('<div class="calendarDays"/>').appendTo(calendar.cfg.months[1])
		]

		calendar.cfg.grid.append('<div class="calendarFooter"/>');

		function calendarClick(e){
			if ($(e.target).is('a:visible') && !$(e.target).hasClass('calendarDisabled')){
				calendar.choose($(e.target).attr('date'));
			}
		}

		calendar.cfg.monthsDays[0].bind('click', calendarClick);
		calendar.cfg.monthsDays[1].bind('click', calendarClick);

		calendar.cfg.prevMonthArrow.bind('click', function(){
			calendar.changeMonth('back');
		});

		calendar.cfg.nextMonthArrow.bind('click', function(){
			calendar.changeMonth('forward');
		});

		if (!calendar.cfg.static){
			$(document).bind('click', function(e){
				if (e.target == calendar.cfg.icon[0] || e.target == calendar.cfg.obj[0] || $(e.target).closest('div.calendar')[0] == calendar.cfg.obj[0]){
					e.stopPropagation();
				} else {
					calendar.hide(true);
				}
			});
		}

		if (calendar.cfg.icon){
			calendar.cfg.icon.bind('click', function(){
				calendar.toggle();
			});
		}

		if (calendar.cfg.static){
			calendar.show();
			calendar.build();
		} else {
			if (calendar.cfg.disabled){
				calendar.disable();
			}
			calendar.hide(true);
		}

	}

	$.extend(calendar, {
		dayNames: ''
	});

	for (var i = 0; i < 7; i++)
	{
		var cls = (i == 0) ? 'calendarMonday' : (i == 6) ? 'calendarSunday' : '';
		calendar.dayNames += '<div' + (cls ? ' class="'+cls+'"' : '') + '><span>' + Date.CultureInfo.abbreviatedDayNames[i == 6 ? 0 : i + 1] + '</span></div>';
	}

	calendarInit();

	return calendar;
}

	$.fn.calendar();

});
