$(document).ready(function() {
	var prevent = false;
	var schedule = $('#schedule');
	var dayHeaderWidth;
	var container = undefined;
	var leftCoordinates = {};
	// Базовый uri для загрузки результатов
	var BASE_URI = '/matches-results-json';
	var REFRESH_INTERVAL = 60000; // милисекунд

	var a = 1; // Торможение в еденицах СИ
	var REFRESH_RATE = 33.3333333;
	var currentSpeed = undefined;
	var timeCathingSpeed = undefined;
	var keepMoving = false;
	var draggingMode = false;
	var timerId = null;
	var prevPos = {
		x : undefined,
		y : undefined
	}
	var maxSpeed = 70;
	var diffPos = {
		x : 0
	}
	var startDragging = false;
	var scheduleRect;

	// Ищу все дни с матчами
	var days = $('.day', schedule);

	if (0 == days.length) {
		return;
	}

	removeAllLinksForIE(schedule);

	function removeAllLinksForIE(node) {
		if ($.browser.msie) {
			$('a', node).each(
			function() {
				var $a = $(this);
				$a.parent().attr('href', $a.attr('href'));
				$a.replaceWith($a.text());
			});
		}
	};

	scheduleRect = getOffsetRect(schedule);

	var maxPosition = -(getOffsetRect(days[days.length - 1]).right - scheduleRect.width - scheduleRect.left - ($('#container', schedule).css('left') ? parseInt($('#container', schedule).css('left')) : 0));

	container = {
		jqNode : $('#container', schedule),
		node : $('#container', schedule).get(0),
		getPosition : function(){
			return this.node.style.left ? parseInt(this.node.style.left) : 0;
		},
		setPosition : function(position) {
			position = parseFloat(position);

			if (position > 0) {
				position = 0;
				$('[data-day-header]:first', container.jqNode).css('margin-left', 0);
				clearInterval(timerId);
				container.node.style.left = position + 'px';
				return;
			} else if (position < maxPosition) {
				position = maxPosition;
				clearInterval(timerId);
				container.node.style.left = position + 'px';
				return;
			}

			container.node.style.left = position + 'px';
			getLeftDayNode(position);
			getRightDayNode(position);
		}
	}

	dayHeaderWidth = $('[data-day-header]:first', schedule).width();
	for (var i = 0; i < days.length; i++) {
		var dayRect = getOffsetRect(days[i]);
		leftCoordinates[dayRect.left - scheduleRect.left - container.getPosition()] = {
			node: days[i],
			rect: dayRect,
			dayHeader: {
				node: $('[data-day-header]:first', days[i]).get(0),
				rect: getOffsetRect($('[data-day-header]:first', days[i]).get(0))
			}
		}
	}

	function getLeftDayNode(position)
	{
		var maxLeftStack = 2;
		var leftDays = [];

		if (false === (maxLeftStack > 0)) {
			return;
		}

		for (var coor in leftCoordinates) {

			if ((coor > (-position) + dayHeaderWidth * (maxLeftStack - 1))
			&& (coor < (-position) + dayHeaderWidth * maxLeftStack)
			&& leftDays.length >= maxLeftStack) {
				leftCoordinates[coor].dayHeader.node.style.marginLeft = 0;

				var fixLeftDays = leftDays.slice(-maxLeftStack).reverse();
				for (var i = 0, totalWidth = 0, rightOffset = 0; i < fixLeftDays.length; i++) {
					totalWidth += fixLeftDays[i].rect.width;
					rightOffset += dayHeaderWidth;
					fixLeftDays[i].dayHeader.node.style.marginLeft = (totalWidth - rightOffset) + 'px';
				}
				return;

			// Те дни, которые должны показываться "прилипшимы" к левой стороне
			} else if (coor < (-position) + dayHeaderWidth * maxLeftStack) {
				leftDays.push({
					'coordinate' : coor,
					'node' : leftCoordinates[coor].node,
					'rect' : leftCoordinates[coor].rect,
					'dayHeader' : leftCoordinates[coor].dayHeader
				});

			// День, который находится справа, от самого левого прилипшего
			} else {
				var nextAfterLeftDay = leftCoordinates[coor];
				break;
			}
		}

		if (0 == leftDays.length) {
			return;
		}

		// День справа от самого левого из видимых, т.е. тот,
		// которв свободном полете
		if (nextAfterLeftDay) {
			nextAfterLeftDay.dayHeader.node.style.marginLeft = 0;
		}

		var visibleleftDays = leftDays.slice(-maxLeftStack);
		for (var i = 0; i < visibleleftDays.length; i++) {
			var marginLeft;
			marginLeft = ((-position) - visibleleftDays[i].coordinate) + (i * dayHeaderWidth);

			if (marginLeft < 0) {
				continue;
			}

			visibleleftDays[i].dayHeader.node.style.marginLeft = marginLeft + 'px';
			continue;
		}
	}

	function getRightDayNode(position)
	{
		var tooRightDays = false;
		for (var coor in leftCoordinates) {
			if (tooRightDays) {
				leftCoordinates[coor].dayHeader.node.style.marginLeft = '0px';
				continue;
			} else if (lastLoop) {
				leftCoordinates[coor].dayHeader.node.style.marginLeft = offset + 'px';
				tooRightDays = true;
				continue;
			} else if ((coor > (-position) + scheduleRect.width - dayHeaderWidth * 2)
			&& ((coor < (-position) + scheduleRect.width - dayHeaderWidth))) {
				var lastLoop = true;
				leftCoordinates[coor].dayHeader.node.style.marginLeft = 0;
				var offset = dayHeaderWidth - leftCoordinates[coor].rect.width;
				continue;
			} else if (coor < (-position) + scheduleRect.width - dayHeaderWidth) {

			} else {
				var rightDay = leftCoordinates[coor];
				var marginLeft = (((-position) + scheduleRect.width) - coor - dayHeaderWidth) + 'px';
				rightDay.dayHeader.node.style.marginLeft = marginLeft;
				break;
			}
		}
	}

	schedule.mousedown(function(e){
		if (e.target.nodeName == 'A') {
			e.preventDefault();
		}

	});
	schedule.click(function(e){
		if (prevent === true) {
			e.preventDefault()
			prevent = false;
		}
		return;
		setTimeout(function(){
			if (e.target.nodeName == 'A') {
				if (true === startDragging) {
					e.preventDefault();
					startDragging = false;
				}
			}
		}, 0)
	});

	container.jqNode.mousedown(startDrag);
	container.jqNode.dblclick(function(e){
		e.preventDefault();
		removeSelection();
	})
	$(schedule).mouseup(stopDrag);
	$(schedule).mousemove(watching);

	// При наведении на матч показываю матч-меню-палатку
	$('.cell-info').hover(
	function(){
		$('dl.menu', $(this)).css('visibility', 'visible')
	}, function(){
		$('dl.menu', $(this)).css('visibility', 'hidden')
	});

	$('.cell-info dl.menu dt').hover(
	function(){
		$(this).addClass('hover');
	},
	function(){
		$(this).removeClass('hover');
	}
	);

	$('#prev-matches').mousedown(startMove);
	$('#prev-matches').mouseup(stopMove);
	$('#next-matches').mousedown(startMove);
	$('#next-matches').mouseup(stopMove);

	container.setPosition(container.getPosition());

	initRefreshingMatchesResults();

	function initRefreshingMatchesResults()
	{
		// Если в текущем (сегодняшнем) дне нет матчей, то не
		// включаю авторефрешинг
		if (0 == $('div.active', schedule).length) {
			return;
		}

		var seasons = eval(schedule.attr('data-seasons'));
		var uri = BASE_URI;

		// К основному адресу дописываю массив сезонов, с каких надо
		// брать результаты
		for (var i = 0; i < seasons.length; i++) {
			uri += ((0 == i) ? '?' : '&') + 'seasons[]=' + seasons[i];
		}

		setInterval(function() {

			$.get(uri, function(data){
				var $day = $('div.day', $(data));


				$day.each(function(){

//					$('.match[data-match-id="' + $(this).attr('data-match-id') + '"] .cell-info', schedule).html($('.cell-info', this).html());

//					var t = '.match[data-match-id="' + $(this).attr('data-match-id') + '"] .cell-info';
//					var l = $('.match[data-match-id="' + $(this).attr('data-match-id') + '"] .cell-info', schedule).length;


					var $new = $(this);
					var $old = $('[data-date="' + $(this).attr('data-date') + '"]', schedule);

					var $h2 = $('h2', $old);
					removeAllLinksForIE($new);

//					$('h2', $new).replaceWith($('h2', $old));

					$old.html($new.html());
					$('h2', $old).replaceWith($h2);

					$('.cell-info', $old).hover(
						function(){
							$('dl.menu', $(this)).css('visibility', 'visible')
						}, function(){
							$('dl.menu', $(this)).css('visibility', 'hidden')
					});

					$('.cell-info dl.menu dt', $old).hover(
						function(){
							$(this).addClass('hover');
						},
						function(){
							$(this).removeClass('hover');
						}
					);
				});

			});
		}, REFRESH_INTERVAL)
	}

	function startDrag()
	{
		prevent = false;
		removeSelection();
		draggingMode = true;
		clearInterval(timerId);
		setCurrentSpeed(0);
		startDragging = false;
	}


	function stopDrag(e)
	{
		draggingMode = false;

		if ((false === startDragging) && (e.target.nodeName != 'A')) {
			if (($(e.target).attr('data-day-header')) || ($(e.target).closest('[data-day-header]').length)) {
				startPosition = container.getPosition();
				var dayRect = getOffsetRect($(e.target).closest('div.day'));

				var to = scheduleRect.left - (dayRect.left);
				var maxPossiblePath = (maxSpeed * maxSpeed) / (2 * a) + maxSpeed / 2;

				if (maxPossiblePath >= Math.abs(to)) {
					goToPosition(to);

				} else {
					clearInterval(timerId);

					// Сколько циклов "ехать" прямолинейно
					var cicleCount = Math.ceil((Math.abs(to) - maxPossiblePath) / maxSpeed);
					setCurrentSpeed(to > 0 ? -maxSpeed : maxSpeed);

					timerId = setInterval(function(){
						container.setPosition(container.getPosition() - getCurrentSpeed());
						to += getCurrentSpeed();
						if (--cicleCount <= 0) {
							clearInterval(timerId);
							goToPosition(to)
						}
					}, REFRESH_RATE);
				}

			} else if ($(e.target).attr('href')) {
				switch (e.button) {
					case (0):
					case (1):
						location = $(e.target).attr('href');
						$('dl.menu').css('visibility', 'hidden');
						$('dl.menu dt').removeClass('hover');
						break;

	//							case (1):
	//								window.open($(e.target).attr('href'));
	//								break;
				}
			}

			return;
		}

		removeSelection();
		prevPos = {
			x : undefined,
			y : undefined
		}

		if ((undefined !== timeCathingSpeed) && (200 > (new Date().getTime() - timeCathingSpeed))) {
			timeCathingSpeed = undefined;
			realese();
		}

		if ((e.target.nodeName == 'A') && (startDragging)) {
			startDragging = false;
			prevent = true;
			e.preventDefault()
		}

		startDragging = false;
	}

	function goToPosition(to)
	{
		var w = -a;
		var D = w * w - 8 * to * w;

		if (to < 0) {
			D = -D;
		}

		var V1 = (-w + Math.sqrt(D)) / -2;
		var V2 = (-w - Math.sqrt(D)) / -2;

		if ((V1 < 0) && (V2 > 0)) {
			var resultV = V2;
		} else if ((V1 > 0) && (V2 < 0)) {
			resultV = V1;
		} else {
			return;
		}

		// Путь теоретический
		var St = -(resultV * resultV) / (2 * w) + resultV / 2;

		// Определяю путь дискретный
		var tempresultV = resultV;
		for (var Sd = 0; true;) {

			Sd += 1 * tempresultV;
			var absSpeed = Math.abs(tempresultV);

			if (absSpeed < a) {
				break;
			}

			tempresultV = (tempresultV > 0) ? tempresultV - a : tempresultV + a;
		}

		if (to < 0) {
			St = -St;
			Sd = -Sd;
			resultV = -resultV;
		}

		setCurrentSpeed(resultV);
		realese(St - Sd);
	}

	function watching(e)
	{
		if (!draggingMode) {
			return;
		}

		removeSelection();

		var currPos = {
			x : e.clientX
		}

		if (prevPos.x) {
			diffPos = {
				x : currPos.x - prevPos.x
			}

			startDragging = true;
			container.setPosition(container.getPosition() + diffPos.x);
		}

		prevPos.x = currPos.x;
		setCurrentSpeed(2 * diffPos.x);
		timeCathingSpeed = new Date().getTime();
	}

	function setCurrentSpeed(speed)
	{
		if (Math.abs(speed) < maxSpeed) {
			currentSpeed = speed;
		} else {
			currentSpeed = currentSpeed < 0 ? -1 * maxSpeed : maxSpeed;
		}
	}

	function getCurrentSpeed()
	{
		return 1 * currentSpeed;
	}

	function removeSelection(){
		if (window.getSelection) {
			window.getSelection().removeAllRanges();
		} else if (document.selection && document.selection.clear) {
			document.selection.clear();
		}
	}

	function startMove(e)
	{
		var offset;
		if (offset = $(this).css('background-position')) {
			$(this).css('background-position', offset.split(' ')[0] + ' -430px')
		} else if (offset = $(this).css('background-position-y')) {
			$(this).css('background-position-y', ' -430px')
		}

		clearTimeout(timerId);
		var button = e.target;
		setCurrentSpeed(parseFloat(button.getAttribute('data-speed')));
		keepMoving = true;

		timerId = setInterval(function(){
			container.setPosition(container.getPosition() + getCurrentSpeed());
		}, REFRESH_RATE);
	}

	function stopMove()
	{
		var offset;
		if (offset = $(this).css('background-position')) {
			$(this).css('background-position', offset.split(' ')[0] + ' -345px')
		} else if (offset = $(this).css('background-position-y')) {
			$(this).css('background-position-y', ' -345px')
		}
		clearTimeout(timerId);
		realese();
	}

	// Расписание отпущено и движется по инерции
	function realese(correction)
	{
		clearTimeout(timerId);
		var x1 = container.getPosition()
		timerId = setInterval(function(){

			var currentSpeed = getCurrentSpeed();
			x1 += 1 * currentSpeed;

			var absSpeed = Math.abs(currentSpeed);
			if (absSpeed < a) {
				clearTimeout(timerId);

				if (correction) {
					container.setPosition(x1 + correction);
				} else {
					container.setPosition(x1);
				}

				return;
			}

			setCurrentSpeed(currentSpeed > 0 ? currentSpeed - a : currentSpeed + a);

			container.setPosition(x1);
		}, REFRESH_RATE);
	}

	// Функция взята и обдуманна отсюда
	// http://javascript.ru/ui/offset
	// Точки с запятой расставил ЛИЧНО!!!
	function getOffsetRect(elem) {
		if (undefined === elem) {
			return undefined;
		}

		if (elem.get) {
			elem = elem.get(0);
		}

		if (undefined == elem) {
			return undefined;
		}

		// Получить ограничивающий прямоугольник для элемента
		var box = elem.getBoundingClientRect();

		// Задать две переменных для удобства
		var body = document.body;
		var docElem = document.documentElement;

		// Вычислить прокрутку документа. Все браузеры, кроме IE,
		// поддерживают pageXOffset/pageYOffset, а в IE, при наличии
		// DOCTYPE прокрутка вычисляется либо на documentElement(<html>),
		// иначе на body - что есть то и берем
		var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
		var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;

		// Документ(html или body) бывает сдвинут относительно окна
		// (IE). Получаем этот сдвиг.
		var clientTop = docElem.clientTop || body.clientTop || 0;
		var clientLeft = docElem.clientLeft || body.clientLeft || 0;

		// Прибавляем к координатам относительно окна прокрутку и
		// вычитаем сдвиг html/body, чтобы получить координаты
		// относительно документа
		var top  = box.top +  scrollTop - clientTop;
		var left = box.left + scrollLeft - clientLeft;
		var right = box.right + scrollLeft - clientLeft;

		return {
			top: Math.round(top),
			left: Math.round(left),
			right: Math.round(right),
			width: Math.round(right - left)
		}
	}
});


