var courtCalendar = {
	
	DOM: {
	//Для запоминания текущих DOM-элементов
		'current': {}
	},
	//Для запоминания данных по текущему календарю
	calendar: {
		index: 0
	},
	//Данные для ajax-запросов
	ajax: {
		'date': {},
		'path': {},
		'timeout': 30000
	},
	//Кол-во календарей на странице
	sum: 0,
	//TRUE - возможность загрузки календаря разблокирована
	load: true,
	//TRUE - Календарь выводится в блоке
	isBlock: false,
	//Значения по умолчанию
	data: {
		'cellHeight': 120
	},
	
	
	/**
	 * Объявляем внутренние переменные и обработчики сообытий
	 */
	init: function() {
		//Запоминаем часто используемые DOM-элементы
		this.setDOM();
		//Выводится ли календарь в блоке или на странице
		this.isBlock = this.DOM.$calendar.hasClass('is_block');
		//Объявляем обработчики сообытий
		this.bind();
		//Устанавливаем адрес для отправки запроса на получение календаря
		this.setAjaxPath();
		//Устанавливаем высоту календаря
		this.setCalendarHeight();
	},
	
	
	/**
	 * Запоминаем часто используемые DOM-элементы
	 */
	setDOM: function() {
		//Окно бразуера
		this.DOM.$window = $(window);
		//Левая колонка
		this.DOM.$colLeft = $('.l-column--left');
		//Футер
		this.DOM.$footer = $('.l-footer');
		//Элементы календаря
		this.setDOMCalendar();
	},
	
	
	/**
	 * Запоминаем DOM-элементы календаря
	 */
	setDOMCalendar: function() {
		//Календарь
		this.DOM.$calendar = $('.js-court_calendar');
		//Спинер загрузки
		this.DOM.$spiner = this.DOM.$calendar.find('.js-court_calendar-spiner');
		//Определяем кол-во календарей на странице
		this.sum = this.DOM.$calendar.length;
		
		//Если на странице 1 календарь, то запоминаем его DOM-элементы
		if (this.sum == 1) {
			//DOM-элемент текущего календаря
			this.DOM.current.$calendar = this.DOM.$calendar;
			//Запоминаем DOM-элементы текущего календаря
			this.setDOMCalendarCurrent();
		}
	},
	
	
	/**
	 * Запоминаем DOM-элементы текущего календаря
	 */
	setDOMCalendarCurrent: function() {
		//Контейнер, в котором расположен календарь
		this.DOM.current.$container = this.DOM.current.$calendar.parent();
		//Панель управления
		this.DOM.current.$controlPanel = this.DOM.current.$calendar.find('.js-court_calendar-control_panel');
		//Спинер загрузки у текущего календаря
		this.DOM.current.$spiner = this.DOM.current.$calendar.find('.js-court_calendar-spiner');
		//Тело текущего календаря
		this.DOM.current.$body = this.DOM.current.$calendar.find('.js-court_calendar-body');
		//Сообщение об ошибке
		this.DOM.current.$error = this.DOM.current.$calendar.find('.js-court_calendar-error');
	},
	
	
	/**
	 * Функция устанавливает необходимые адресы для отправки ajax-запросов
	 * для каждого календаря в наборе
	 */
	setAjaxPath: function() {
		for (var i = 0; i < this.sum; i++) {
			if (!this.ajax.path[i]) {
				//На получение календаря
				this.ajax.path[i] = $(this.DOM.$calendar[i])
										.find('.js-court_calendar-form')
										.attr('action');
			}
		}
	},
	
	
	/**
	 * Объявляем обработчики сообытий
	 */
	bind: function() {
		//Для календарей, выводимых на странице, а не в блоке
		if (!this.isBlock) {
			//Обработчик изменения размеров окна браузера
			this._bindResizeWindow();
			
			//Если на странице один календарь
			if (this.sum == 1) {
				//Обработчик нажатия клавиш
				this._bindKeyPress();
			}
		}
		
		//Обработчик событий календаря
		this._bindCalendar();
	},
	
	
	/**
	 * Обработчик изменения размеров окна браузера
	 */
	_bindResizeWindow: function() {
		var self = this;
		
		this.DOM.$window.resize(function(){ 
			//Устанавливаем высоту календаря относительно левой колонки, если спинер загрузки скрыт
			if (self.DOM.$spiner.hasClass('g-hidden')) {
				self.setCalendarHeight();
			}
		});
	},
	
	
	/**
	 * Обработчик нажатия клавиш
	 */
	_bindKeyPress: function() {
		var self = this;
		
		//Обработчик нажатия клавиш стрелок влево и вправо
		$(document).keydown(function(e) {
			var load = false,
				keycode = (window.event) ? e.keyCode : e.which ;
			
			switch (keycode) {
				//Стрелка влево
				case 37:
					self.ajax.date[0] = {
						'month': $('#court_calendar_prev_month').val(),
						'year': $('#court_calendar_prev_year').val()
					}
					load = true;
					break
					
				//Стрелка вправо
				case 39:
					self.ajax.date[0] = {
						'month': $('#court_calendar_next_month').val(),
						'year': $('#court_calendar_next_year').val()
					}
					load = true;
					break
			}
			
			//загружаем календарь с выбранным месяцем
			if (load) {
				self.loadCalendar();
			}
		});
	},
	
	
	/**
	 * Объявляем обработчики сообытий календаря
	 */
	_bindCalendar: function() {
		//Обработчик событий панели управления
		this._bindControlPanel();
	},
	
	
	/**
	 * Обработчик событий панели управления
	 */
	_bindControlPanel: function() {
		var self = this;
		
		//Обработчик выбора месяца на панели управления
		this.DOM.$calendar.delegate('.js-court_calendar-control_panel-month', 'click', function(){
			var $this = $(this),
				index = 0;
			
			//Если на странице более 1 календаря, то определяем индекс календаря текущей панели
			if (self.sum > 1) {
				//DOM-элемент текущего календаря
				self.DOM.current.$calendar = $this.closest('.js-court_calendar');
				//Индекс текущего календаря
				self.getCalendarIndex();
				index = self.calendar.index;
			}
			
			//запоминаем выбранные месяц и год
			self.ajax.date[index] = {
				'month': $this.find('.js-court_calendar-month').val(),
				'year': $this.find('.js-court_calendar-year').val()
			}
			
			//загружаем календарь с выбранным месяцем
			self.loadCalendar();
		});
	},
	
	
	/**
	 * Функция определяет индекс у текущего календаря
	 */
	getCalendarIndex: function() {
		for (var i = 0; i < this.sum; i++) {
			if (this.DOM.current.$calendar[0] == this.DOM.$calendar[i]) {
				this.calendar.index = i;
				break;
			}
		}
	},
	
	
	/**
	 * Функция загрузки календаря
	 */
	loadCalendar: function() {
		var self = this,
			i = this.calendar.index;
		
		//Если на странице более 1 календаря, то запоминаем DOM-элементы текущего календаря
		if (self.sum > 1) {
			this.setDOMCalendarCurrent();
		}
		
		//Загружаем календарь
		if (this.ajax.path && this.load) {
			//На время загрузки блокируем её вызов
			this.load = false;
			//Скрываем календарь
			this.DOM.current.$body.addClass('g-hidden');
			//Расскрываем спинер загрузки
			this.DOM.current.$spiner.removeClass('g-hidden');
			
			$.ajax({
				type: 'post',
				url: this.ajax.path[i],
				data: this.ajax.date[i],
				dataType: 'html',
				timeout: this.ajax.timeout,
				success: function(output){
					if (output) {
						//Выводим календарь
						self.showCalendar(output);
					} else {
						//Выводим сообщение об ошибке
						self.showError();
					}
					
					//Разблокируем возможность загрузки календаря
					self.load = true;
				},
				error: function(){
					//Выводим сообщение об ошибке
					self.showError();
					//Разблокируем возможность загрузки календаря
					self.load = true;
				}
			});
		}
	},
	
	
	/**
	 * Функция отображает текущий календарь
	 * 
	 * @param str	output		Календарь, который нужно вывести
	 */
	showCalendar: function(output) {
		//Скрываем спинер загрузки
		this.DOM.current.$spiner.addClass('g-hidden');
		//Скрываем сообщение об ошибке
		this.DOM.current.$error.addClass('g-hidden');
		//Выводим календарь и запускаем событие смены календаря для других модулей
		this.DOM.current.$container
			.html(output)
			.trigger('calendarChange');
		
		//DOM-элементы календаря
		this.setDOMCalendar();
		//Объявляем обработчики сообытий
		this.bind();
		//Устанавливаем адрес для отправки запроса на получение календаря
		this.setAjaxPath();
		//Устанавливаем высоту календаря
		this.setCalendarHeight();
	},
	
	
	/**
	 * Функция отображает сообщение об ошибке
	 */
	showError: function() {
		if (!this.isBlock) {
			//Скрываем панель управления
			this.DOM.current.$controlPanel
				.find('.js-court_calendar-control_panel-wrapper')
				.addClass('g-hidden');
		}
		//Скрываем спинер загрузки
		this.DOM.current.$spiner.addClass('g-hidden');
		//Выводим сообщение об ошибке
		this.DOM.current.$error.removeClass('g-hidden');
	},
	
	
	/**
	 * Функция устанавливает высоту календаря
	 */
	setCalendarHeight: function() {
		var i;
		
		for (i = 0; i < this.sum; i++) {
			if (this.isBlock) {
				//Фиксируем высоту календаря в блоке
				this.setCalendarBlockHeight(this.DOM.$calendar.eq(i));
			} else {
				//Устанавливаем высоту календаря на странице относительно левой колонки
				this.setCalendarPageHeight(this.DOM.$calendar.eq(i));
			}
		}
	},
	
	
	/**
	 * Функция устанавливает высоту календаря на странице 
	 * относительно левой колонки
	 * 
	 * @param obj	$calendar
	 */
	setCalendarPageHeight: function($calendar) {
		var //Тело календаря
			$body = $calendar.find('.js-court_calendar-body'),
			//Ячейки календаря
			$cell = $body.find('.js-court_calendar-body-date'),
			//Кол-во недель в календаре
			sumWeek = $body
						.find('.js-court_calendar-body-dates')
						.children().length;
			height = {
				//высота окна браузера
				'win': this.DOM.$window.height(),
				//Высота календаря по умолчанию
				'defCalendar': this.data.cellHeight * sumWeek + 25,
				//высота содержимого левой колонки
				'colLeft': this.DOM.$colLeft.height(),
				//высота шапки страницы + панель управления
				'header': $body.offset().top,
				//высота футера
				'footer': this.DOM.$footer.height()
			};
			
		//Определяем высоту, которую нужно задать для календаря
		height.calendar = height.win - (height.header + height.footer);
		if (height.calendar <= height.colLeft) {
			height.calendar = height.colLeft;
		}
		if (height.defCalendar >= height.calendar || $calendar.hasClass('js-court_calendar--fixed')) {
			height.calendar = height.defCalendar;
		}

		//Задаем высоту календаря, расскрываем календарь
		$body
			.height(height.calendar)
			.removeClass('g-hidden');
		//Устанавливаем высоту для ячеек календаря
		height.cell = (height.calendar - 25) / sumWeek;
		height.cell = (height.cell > this.data.cellHeight) ? height.cell : this.data.cellHeight;
		$cell.height(height.cell);
	},
	
	
	/**
	 * Функция фиксирует высоту всех календарей в блоках на странице
	 * 
	 * @param obj	$calendar
	 */
	setCalendarBlockHeight: function($calendar) {
		$calendar.css({
			height: $calendar.height()
		});
	}
};

$(function(){
	courtCalendar.init();
});