var Calendar = (function() {

	return function(_element, _pattern, _callback) {
		
		var element, holder, nmonth, nyear, pmonth, pyear, cmonth, cyear, wdays, days;
		
		
		var dt = {
			date: new Date().getDate(),
			month: new Date().getMonth(),
			year: new Date().getFullYear()
		};
				
		var dayNames = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Суб', 'Вс'];
		
		var monthNames = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
		
		var setElement = function(_element) {
			if(!_element)
				throw new Error('Target element wasn\'t specified: new Calendar(targetElement [, startDate]);');
			if(typeof _element == 'string') {
				element = Element.$(_element);
				if(!element) throw new Error('Element with specified id: "' + _element + '" does not exist.');
			} else {
				element = _element;
			}
		}

		var getDaysPerMonth = function(month, year) {
			if(month == 1) return (year && year%4 == 0) ? 29 : 28;
			if(month == 3 || month == 5 || month == 8 || month == 10) return 30;
			return 31;
		}
		
		var getCDay = function(day) {
			return day > 0 ? --day : 6;
		}
		
		var setDays = function(date, month, year) {
			
			if(dt.month > 11) { 
				dt.month = 0; 
				dt.year ++; 
			}
			
			if(dt.month < 0) {
				dt.month = 11;
				dt.year --;
			}

			var date = dt.date;
			var month = dt.month;
			var year = dt.year;

			var n = new Date(year, month, 1);
			
			var day = getCDay(n.getDay());
			
			Element.empty(days);
			
			cmonth.innerHTML = monthNames[month];
			cyear.innerHTML = year;
				
			for(var i = 0; i < day; i ++) {
				var item = new Element.create('span', {'class': 'calendarDay calendarInactive', 'text': '  '});
				Element.inject(item, days);
			}
			
			for(var i = 1, l = getDaysPerMonth(month, year); i <= l; i ++) {
				var cl = (i == date && month == new Date().getMonth() && year == new Date().getFullYear()) ? 'calendarDay calendarActive' : 'calendarDay';
				var link = _pattern.replace(/%DATE/, i).replace(/%MONTH/, (month+1)).replace(/%YEAR/, year);
				var item = new Element.create('a', {'class': cl, 'text': i + ' ', 'href': link});
				Element.inject(item, days);
				Event.addEvent(item, 'click', function(event){
					Event.stopEvent(event);
					_callback(event.srcElement ? event.srcElement.href : event.target.href);
				});
			}
			
		}
		
		var setStructure = function() {
			holder = new Element.create('div', {'class': 'calendar'});
			nmonth = new Element.create('div', {'class': 'calendarControl calendarNMonth', 'text': '&raquo;'});
			cmonth = new Element.create('div', {'class': 'calendarText calendarCMonth', 'text': 'January'});
			pmonth = new Element.create('div', {'class': 'calendarControl calendarPMonth', 'text': '&laquo;'});
			nyear = new Element.create('div', {'class': 'calendarControl calendarNYear', 'text': '&raquo;'});
			pyear = new Element.create('div', {'class': 'calendarControl calendarPYear', 'text': '&laquo;'});
			cyear = new Element.create('div', {'class': 'calendarText calendarCYear', 'text': '2008'});
			wdays = new Element.create('div', {'class': 'calendarWDays'});
			days = new Element.create('div', {'class': 'calendarDays'});
			
			Event.addEvent(nmonth, 'click', function() {
				++ dt.month
				setDays();
			});
			
			Event.addEvent(pmonth, 'click', function() {
				-- dt.month
				setDays();
			});

			Event.addEvent(nyear, 'click', function() {
				++ dt.year
				setDays();
			});

			Event.addEvent(pyear, 'click', function() {
				-- dt.year;
				setDays();
			});
			
			for(var i = 0, l = dayNames.length; i < l; i ++) {
				var wday = new Element.create('span', {'class': 'calendarWDay', 'text': dayNames[i]});
				Element.inject(wday, wdays);
			}
			
			Element.inject([pyear, nyear, cyear, pmonth, nmonth, cmonth, wdays, days], holder);
			Element.inject(holder, element);
		}
		
		setElement(_element);
		setStructure();
		setDays();
		
	}
})();
