/**
 * @projectDescription
 * Скрипт управления просмотром истории.
 *
 * @author Vlad Yakovlev (scorpix@design.ru)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 * @version 0.1.2 (23.02.2009)
 * @requires jQuery
 * @requires jTweener 0.2.1
 */
$(function() {
	/**
	 * Путь к Ajax запросам на сервер.
	 */
	var ajaxPath = '/ajax-history/';

	var pathParts = location.href.split('/');

	if (pathParts[3] && 'en' == pathParts[3]) {
		ajaxPath = '/en' + ajaxPath;
	}

	/**
	 * Массив доступных лет.
	 * @type {Array[Number]}
	 */
	var years = [];

	var blocks = {
		container: $('#content .timeline .container'),
		timeline: $('#content .timeline ul'),
		sections: $('#content .timeline ul .section'),
		runner: $('#content .timeline ul .runner'),
		fader: $('#content .events .fader'),
		events: $('#content .events'),
		timePrev: $('#content .timeline .time_prev'),
		timeNext: $('#content .timeline .time_next')
	};

	blocks.measurer = $('<div class="measurer"></div>').appendTo(blocks.container);

	/**
	 * Текущий индекс года.
	 */
	var curIndex = -1;

	/**
	 * Флаг перемещения при Drag'n'Drop.
	 */
	var isMove = false;

	/**
	 * Позиция бегунка при перемещении в пикселях.
	 * @type {Number}
	 */
	var dndLeft;

	/**
	 * Границы перемещения бегунка (<code>min</code> и <code>max</code>), в пикселях.
	 * @type {Object}
	 */
	var dndLeftBorders;

	/**
	 * Разница между горизонтальными позициями курсора мыши и бегунка, в пикселях.
	 * @type {Number}
	 */
	var dndDiff;

	var sectionWidth;

	var visibleWidth;

	var measurerHeight = blocks.measurer.height();

	var curLeft = getValue(blocks.runner.css('left'));

	var isInit = false;

	var paddingBorder = 34;

	var moveStep = 60;

	var awards = {};

	init();

	setInterval(checkMeasurer, 500);

	$(window).resize(onResize);

	blocks.timeline.click(function(/** @type {Event} */ e) {
		var target = e.target;

		if ('A' == target.nodeName && !$(target).parent().hasClass('selected')) {
			changeYear($(target.parentNode));
		}

		return false;
	});

	blocks.timeNext.mousedown(function() {
		return startTimelineMoving(true);
	});
	blocks.timePrev.mousedown(function() {
		return startTimelineMoving(false);
	});
	blocks.timeNext.mouseup(function() {
		return stopTimelineMoving(true);
	});
	blocks.timePrev.mouseup(function() {
		return stopTimelineMoving(false);
	});

	blocks.timeNext.click(function() {
		return onClickTimelineMoving(true);
	});
	blocks.timePrev.click(function() {
		return onClickTimelineMoving(false);
	});

	blocks.runner.mousedown(startDnd);
	$(document).mousemove(dnd).mouseup(finishDnd);

	/**
	 * Инициализирует год при загрузке страницы.
	 */
	function init() {
		var i = 0;

		blocks.sections.each(function() {
			years.push($(this).find('a').text());

			if ($(this).hasClass('selected')) {
				curIndex = i;
			}

			i++;
		});

		$('#main_content h1 .picture_award').each(function() {
			var prefix = 'award_';
			var classes = $(this).attr('class').split(' ');

			for (var i = 0; i < classes.length; i++) {
				if (prefix == classes[i].substr(0, prefix.length)) {
					awards[parseInt(classes[i].substr(prefix.length))] = $(this);
				}
			}

			$(this).addClass('hidden');
		});

		onResize();
		onScale();
		checkDisable();

		var locationParts = location.href.split('#');

		if (!locationParts[1] || locationParts[1] == years[curIndex]) {
			isInit = true;
			goToVisible();

			return;
		}

		// Если есть якорь, то загружаем год.
		for (var i = 0; i < years.length; i++) {
			if (locationParts[1] == years[i]) {
				changeYear(blocks.sections.eq(i));

				return;
			}
		}

		location.href = '#' + years[curIndex];
	}

	function onScale() {
		sectionWidth = blocks.sections.eq(0).width();
	}

	function onResize() {
		visibleWidth = blocks.container.width();
		goToBorder();
		checkDisable();
	}

	function checkMeasurer() {
		var newHeight = blocks.measurer.height();

		if (newHeight != measurerHeight) {
			measurerHeight = newHeight;
			onScale();
		}
	}

	function onClickTimelineMoving(isFuture) {
		var timelineLeft = getValue(blocks.timeline.css('left'));
		var toLeft = isFuture ? timelineLeft - moveStep : timelineLeft + moveStep;
		var minLeft = visibleWidth - sectionWidth * years.length - paddingBorder;

		if (toLeft < minLeft) {
			toLeft = minLeft;
		} else if (0 < toLeft) {
			toLeft = 0;
		}

		jTweener.removeTween(blocks.timeline);
		jTweener.addTween(blocks.timeline, {
			left: toLeft,
			time: 0.6,
			onComplete: function() {
				checkDisable();
			}
		});

		return false;
	}

	function startTimelineMoving(isFuture) {
		var toLeft = isFuture ? visibleWidth - sectionWidth  * years.length - paddingBorder : 0;
		var fromLeft = getValue(blocks.timeline.css('left'));

		var diff = Math.abs(toLeft - fromLeft);

		jTweener.addTween(blocks.timeline, {
			left: toLeft,
			time: diff / 600,
			transition: 'easeInCubic',
			onComplete: function() {
				checkDisable();
			}
		});

		return false;
	}

	function stopTimelineMoving(isFuture) {
		jTweener.removeTween(blocks.timeline);
		checkDisable();

		return false;
	}

	function checkDisable() {
		var timelineLeft = getValue(blocks.timeline.css('left'));

		if (timelineLeft > visibleWidth - sectionWidth * years.length - paddingBorder) {
			blocks.timeNext.removeClass('time_disable');
		} else {
			blocks.timeNext.addClass('time_disable');
		}

		if (0 > timelineLeft) {
			blocks.timePrev.removeClass('time_disable');
		} else {
			blocks.timePrev.addClass('time_disable');
		}
	}

	function goToVisible() {
		var left = 0;
		var minLeft = visibleWidth - sectionWidth * years.length - paddingBorder;

		if (sectionWidth * (curIndex + 1) + paddingBorder > visibleWidth) {
			left = visibleWidth - sectionWidth * (curIndex + 1) - paddingBorder;

			if (left < minLeft) {
				left = minLeft;
			}

			jTweener.addTween(blocks.timeline, {
				left: left,
				time: 1,
				onComplete: function() {
					checkDisable();
				}
			});
		}
	}

	function goToBorder() {
		var timelineLeft = getValue(blocks.timeline.css('left'));
		var minLeft = visibleWidth - sectionWidth * years.length - paddingBorder;

		if (timelineLeft < minLeft) {
			var toLeft = 0 < minLeft ? 0 : minLeft;

			if ($.browser.mozilla) {
				jTweener.removeTween(blocks.timeline);
				jTweener.addTween(blocks.timeline, {
					left: toLeft,
					time: 1
				});
			} else {
				blocks.timeline.css('left', toLeft);
			}
		}
	}

	/**
	 * Начинает перемещение бегунка.
	 * @param {Event} e Событие onmousedown.
	 */
	function startDnd(e) {
		if (isMove) {
			return true;
		}

		// Чтоб выше по дереву DOM никто не мешал нормальному Dnd.
		e.stopPropagation();

		jTweener.removeTween(blocks.runner);

		/** @type {Number} */
		var curRunnerPos = getValue(blocks.runner.css('left'));

		dndLeft = curRunnerPos;
		blocks.runner.css('left', dndLeft);
		isMove = true;
		dndDiff = parseInt(e.pageX) - dndLeft;

		/** @type {Number} */
		var timelineWidth = blocks.timeline.width();
		/** @type {Number} */
		var halfWidth = timelineWidth / blocks.sections.size() / 2;

		var timelineLeft = parseInt(blocks.timeline.css('left'));

		dndLeftBorders = {
			max: visibleWidth > sectionWidth * years.length ? sectionWidth * years.length : visibleWidth - timelineLeft,
			min: -timelineLeft
		};

		fadeIn();

		return false;
	}

	/**
	 * Перемещение при Dnd.
	 * @param {Event} e Событие onmousemove.
	 */
	function dnd(e) {
		if (!isMove) {
			return true;
		}

		e.stopPropagation();

		/** type {Number} */
		var pageX = parseInt(e.pageX);

		// Вычисляем следующую точку бегунка.
		dndLeft = pageX - dndDiff;

		if (dndLeft < dndLeftBorders.min) {
			dndLeft = dndLeftBorders.min;
		}
		if (dndLeft > dndLeftBorders.max) {
			dndLeft = dndLeftBorders.max;
		}

		blocks.runner.css('left', dndLeft);

		return false;
	}

	/**
	 * Заканчивает перемещение.
	 * @param {Event} e Событие onmouseup.
	 */
	function finishDnd(e) {
		if (!isMove) {
			return true;
		}

		e.stopPropagation();

		/** @type (Number) */
		var timelineWidth = blocks.timeline.width();
		/** @type (Number) */
		var sectionWidth = timelineWidth / blocks.sections.size();
		/** @type (Number) */
		var sectionIndex = Math.ceil(dndLeft / sectionWidth) - 1;

		isMove = false;
		moveToYear(blocks.sections.eq(sectionIndex));

		return false;
	}

	/**
	 * Показывает информацию по выбранному году.
	 * @param {jQuery} newSection Секция, которая теперь будет текущей.
	 */
	function changeYear(newSection) {
		moveToYear(newSection);
		fadeIn();
	}

	/**
	 * Загружает новый год.
	 * @param {jQuery} newSection Новая выбранная секция из списка лет.
	 */
	function moveToYear(newSection) {
		jTweener.removeTween(blocks.runner);

		/** @type jQuery */
		var curSection = blocks.sections.eq(curIndex);
		/** @type Number */
		var newIndex = newSection.prevAll().size();
		/** @type Object */
		var curRunnerPos = getValue(blocks.runner.css('left'));
		/** @type Number */
		var newRunnerPos = sectionWidth * newIndex + Math.round(sectionWidth / 2);
		/** @type Number */
		var newLeftEm = newRunnerPos / measurerHeight;

		if ($.browser.msie) {
			newLeftEm *= 1.012;
		}

		blocks.timeline.find('a').blur();

		blocks.runner.css('left', curRunnerPos);

		jTweener.addTween(blocks.runner, {
			left: newRunnerPos,
			time: 1,
			onComplete: function() {
				blocks.runner.css('left', newLeftEm + 'em');
				oldIndex = curIndex;
				curIndex = newIndex;

				var curYear = years[curIndex];

				for (var awardYear in awards) {
					if (curYear >= awardYear) {
						awards[awardYear].removeClass('hidden');
					} else {
						awards[awardYear].addClass('hidden');
					}
				}

				if (!isInit) {
					isInit = true;
					goToVisible();
				}

				curSection.removeClass('selected');
				newSection.addClass('selected');

				location.href = '#' + years[newSection.prevAll().size()];

				/** @type {jQuery} */
				var newEvent = blocks.events.find('.event_' + years[curIndex]);

				if (newEvent.size()) {
					blocks.events.find('.event_' + years[oldIndex]).addClass('jhidden');
					newEvent.removeClass('jhidden');
					fadeOut();
				} else {
					blocks.events.prepend('<div class="event event_' + years[curIndex] + '"></div>');
					newEvent = blocks.events.find('.event_' + years[curIndex]);

					$.ajax({
						data: { year: years[curIndex] },
						dataType: 'html',
						type: 'GET',
						url: ajaxPath,
						success: function(data) {
							newEvent.html(data).removeClass('jhidden');
							blocks.events.find('.event_' + years[oldIndex]).addClass('jhidden');
							fadeOut();
						}
					});
				}
			}
		});
	}

	/**
	 * Скрывает контент.
	 */
	function fadeIn() {
		if (!blocks.fader.hasClass('hidden')) {
			return;
		}

		blocks.fader.css('opacity', 0).removeClass('hidden');
		jTweener.removeTween(blocks.fader);
		jTweener.addTween(blocks.fader, {
			opacity: 1,
			time: 1,
			onComplete: function() {
				blocks.fader.css('opacity', '');
			}
		});
	}

	/**
	 * Показывает контент.
	 */
	function fadeOut() {
		if (blocks.fader.hasClass('hidden')) {
			return;
		}

		jTweener.removeTween(blocks.fader);
		jTweener.addTween(blocks.fader, {
			opacity: 0,
			time: 1,
			onComplete: function() {
				blocks.fader.addClass('hidden').css('opacity', '');
			}
		});
	}

	function getValue(value) {
		if (-1 !== value.toString().indexOf('em')) {
			return parseInt(value) * measurerHeight;
		}

		return parseInt(value);
	}
});