
	var majDatepicker = new Class({
		Implements: [Options],
		options: {
			id:        false,
			className: false,
			align:     'left',
			calendar:  true,
			clock:     true,
			on_top:    true,
			yearBack:  70,
			yearNext:  10,
			lang: {
				submit: 'Готово',
				month: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
				day: ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс']
			},
			inputFormat:  'Y/m/d H:i',
			outputFormat: 'Y/m/d H:i',
			onUpdate: function() {}
		},
		selectYear:  false,
		selectMonth: false,
		element: false,
		target:  false,
		widget:  false,
		year:    false,
		month:   false,
		day:     false,
		hours:   false,
		minutes: false,
		grid: [],
		current_chunk: false,
		initialize: function(element, target, options)
		{
			this.setOptions(options);
			this.element = element;
			this.target  = target;
			
			var object = this;
			
			if (target.get('value').length)
			{
				this._initDate();
				this._updateDate();
			}
			
			this.widget = new majWidget({
				id: this.options.id,
				className: 'majDatepicker'+(this.options.className ? ' '+this.options.className : ''),
				modal: false,
				close: false,
				minimize: true,
				resizable: false,
				draggable: false,
				title: ' ',
				on_top: this.options.on_top,
				callShow: function(){
					if (!target.get('value').length)
					{
						object._initDate();
						object._updateDate();
					}
				}
			});
			
			var coords = element.getCoordinates();
			
			this.widget.elements.widget.setStyle('top', coords.bottom);
			if (this.options.align == 'right')
			{
				var size = this.widget.elements.widget.getSize();
				this.widget.elements.widget.setStyle('left', coords.right-size.x);
			}
			else
			{
				this.widget.elements.widget.setStyle('left', coords.left);
			}
			
			element.addEvent('click', function(e){
				e.stopPropagation();
			});
			
			this.widget.elements.widget.addEvent('click', function(e){
				e.stopPropagation();
			});
			
			element.addEvent('click', function(){
				object.widget.toggle();
			});
			
			document.addEvent('click', function(){
				object.widget.hide();
			});
			
			if (this.options.calendar) this._createCalendar();
			if (this.options.clock) this._createClock();
		},
		_initDate: function()
		{
			var object = this;
			var format = object.options.inputFormat;
			var mods   = ['d', 'm', 'Y', 'H', 'i'];
			
			function getDateValue(param, pass, i)
			{
				i = i || 0;
				
				var pattern = format;
				$each(mods, function(mod){
					if (mod != param)
					{
						pattern = pattern.replace(mod, '\\d+\\b');
					}
					else
					{
						pattern = pattern.replace(mod, '(\\d+\\b)');
					}
				});
				
				var r = new RegExp(pattern).exec(object.target.get('value'));
				if (r && r[1])
				{
					return r[1].toInt()+i;
				}
				
				return pass;
			}
			var current  = new Date();
			this.year    = getDateValue('Y', current.getFullYear());
			this.month   = getDateValue('m', current.getMonth(), -1);
			this.day     = getDateValue('d', current.getDate());
			
			this.hours   = getDateValue('H', current.getHours()).toString();
			this.hours   = this.hours.length > 1 ? this.hours : '0'+this.hours;
			this.minutes = getDateValue('i', current.getMinutes()).toString();
			this.minutes = this.minutes.length > 1 ? this.minutes : '0'+this.minutes;
		},
		_updateDate: function()
		{
			var format = this.options.outputFormat;
			
			var mods = {
				Y: this.year,
				m: this.month.toInt()+1,
				d: this.day,
				H: this.hours,
				i: this.minutes
			};
			
			var val = format;
			$each(mods, function(mod, i){
				val = val.replace(i, mod);
			});
			
			this.target.set('value', val);
			
			if (this.selectYear)
			{
				current = this.selectYear.getElement(':selected');
				if (current != null) current.set('selected', false);
				
				updated = this.selectYear.getElement(':value('+this.year+')');
				if (updated != null) updated.set('selected', true);
			}
			
			if (this.selectMonth)
			{
				current = this.selectMonth.getElement(':selected');
				if (current != null) current.set('selected', false);
				
				updated = this.selectMonth.getElement(':value('+this.month+')');
				if (updated != null) updated.set('selected', true);
			}
			
			this.target.fireEvent('change');
			
			this.options.onUpdate(this);
		},
		_createCalendar: function()
		{
			var object = this;
			var date = new Date();
			
			var header = object.widget.elements.headerText;
			var content = object.widget.elements.content;
			var container = new Element('div').addClass('majDatepicker-date').inject(content);
			
			this.selectYear = new Element('select').inject(header);
			var back = date.getFullYear()-object.options.yearBack;
			var next = date.getFullYear()+object.options.yearNext;
			for (var i = back; i < next; i++) {
				var opt = new Element('option').set('value', i).set('text', i).inject(this.selectYear);
				if (i == object.year) opt.set('selected', true);
			}
			this.selectYear.addEvent('change', function(){
				object.year = object.selectYear.get('value');
				object._updateGrid();
				object._updateDate();
			});
			
			this.selectMonth = new Element('select').inject(header);
			for (var i = 0; i < 12; i++) {
				var opt = new Element('option').set('value', i).set('text', object.options.lang.month[i]).inject(this.selectMonth);
				if (i == object.month) opt.set('selected', true);
			}
			this.selectMonth.addEvent('change', function(){
				object.month = object.selectMonth.get('value');
				object._updateGrid();
				object._updateDate();
			});
			
			var current = new Element('span').set('text', '↓').addClass('majDatepicker-cd').inject(header);
			current.addEvent('click', function(){
				object.year    = date.getFullYear();
				object.month   = date.getMonth();
				object.day     = date.getDate();
				
				object._updateGrid();
				object._updateDate();
			});
			
			var table = new Element('table').addClass('majDatepicker-table').inject(container);
			var day_header = new Element('tr').inject(table);
			for (var i = 0; i < 7; i++)
			{
				new Element('th').set('text', object.options.lang.day[i]).addClass('d'+i).inject(day_header);
			}
			
			for (var l = 0; l < 6; l++)
			{
				object.grid[l] = [];
				var line = new Element('tr').inject(table);
				for (var i = 0; i < 7; i++)
				{
					var chunk = new Element('td').addClass('d'+i).inject(line);
					chunk.addEvent('click', function(){
						var val = this.get('value');
						if (!val) return false;
						
						if (object.current_chunk) object.current_chunk.removeClass('current');
						this.addClass('current');
						object.day = val;
						object.current_chunk = this;
						object._updateDate();
					});
					object.grid[l][i] = chunk;
				}
			}
			
			return object._updateGrid();
		},
		_updateGrid: function()
		{
			var object = this;
			
			var date = new Date(object.year, object.month, 1);
			var first_day = date.getUTCDay();
			var last_date = 1;
			
			for (var l = 0; l < 6; l++)
			{
				for (var i = 0; i < 7; i++)
				{
					var chunk = object.grid[l][i];
					
					chunk.set('value', 0);
					chunk.removeClass('day');
					chunk.removeClass('current');
					if (l == 0 && i < first_day || date.getDate() < last_date) {
						chunk.set('text', '');
					}
					else
					{
						chunk.addClass('day');
						chunk.set('text', last_date);
						chunk.set('value', last_date);
						
						if (last_date == object.day) {
							chunk.addClass('current');
							object.current_chunk = chunk;
						}
						date.setDate(++last_date);
					}
				}
			}
		},
		_createClock: function(){
			var object = this;
			
			var content   = object.widget.elements.content;
			var container = new Element('div').addClass('majDatepicker-time').inject(content);
			var hours     = new Element('input').addClass('hours').set('type', 'text').set('maxlength', 2).set('value', this.hours).inject(container);
			new Element('span').set('text', ':').inject(container);
			var minutes   = new Element('input').addClass('minutes').set('type', 'text').set('maxlength', 2).set('value', this.minutes).inject(container);
			var current   = new Element('span').set('text', '↓').addClass('majDatepicker-ct').inject(container);
			
			var isInt = /\d+\b/;
			hours.addEvent('keyup', function(){
				var value = hours.get('value');
				
				if (value.length && !isInt.exec(value)) hours.set('value', '00');
				if (value.length && value.toInt() > 23) hours.set('value', '23');
				
				if (value.length)
				{
					var updated = hours.get('value');
					object.hours = updated.length > 1 ? updated : '0'+updated;
					
					object._updateDate();
				}
			});
			hours.addEvent('blur', function(){var value = hours.get('value'); if(value.length) return true; hours.set('value', '00'); object.hours = '00'; object._updateDate();});
			
			minutes.addEvent('keyup', function(){
				var value = minutes.get('value');
				
				if (value.length && !isInt.exec(value)) minutes.set('value', '00');
				if (value.length && value.toInt() > 59) minutes.set('value', '59');
				
				if (value.length)
				{
					var updated = minutes.get('value');
					
					object.minutes = updated.length > 1 ? updated : '0'+updated;
					object._updateDate();
				}
			});
			minutes.addEvent('blur', function(){
				var value = minutes.get('value');
				if(value.length)
				{
					if (value.length == 1)
					{
						minutes.set('value', '0'+value);
					}
					return true;
				}
				
				minutes.set('value', '00');
				object.minutes = '00';
				object._updateDate();
			});
			
			current.addEvent('click', function(){
				var date = new Date();
				
				object.hours = date.getHours();
				object.hours = object.hours.toString().length > 1 ? object.hours : '0'+object.hours;
				object.minutes = date.getMinutes();
				object.minutes = object.minutes.toString().length > 1 ? object.minutes : '0'+object.minutes;
				
				hours.set('value', object.hours);
				minutes.set('value', object.minutes);
				
				object._updateDate();
			});
		}
	});
	
	Element.implement({
		mwDatepicker: function(target, options) { if(!options){options=target;target=this;} return new majDatepicker(this, target, options); }
	});
