/**
 * @projectDescription
 * Аниматор для информации по людям.
 *
 * Логика такова:
 * Скрываем сначала линки , чтоб юзер увидел, что они существуют.
 * При ховере на фотке линк появляется. При нажатии анимируется появление
 * текстового блока. Во время анимации можно нажать на другую ссылку (но можно
 * и не нажимать - зачем нам баги :). Можно нажать куда-нить вне блока с историей - открытая история закроется.
 * Линк исчезает, если мы закрыли текстовый блок и убрали ховер с фотки.
 *
 * @author Vlad Yakovlev (scorpix@design.ru)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 * @version 0.2 (12.12.2008)
 * @requires jQuery 1.2.6
 * @requires jTweener
 */
(function() {
	/**
	 * Префиксы блоков, с которыми будем работать (нужны для определения идентификатор статьи).
	 */
	var prefixes = {
		photo: 'photo-',
		story: 'story-'
	};

	/**
	 * Вся информация о блоках, которая вытаскивается по идентификатору:
	 * <ul>
	 *  <li><code>link</code> - jQuery объект блока линка,</li>
	 *  <li><code>photo</code> - jQuery объект блока с фото,</li>
	 *  <li><code>story</code> - jQuery объект блока с историей (не читайте их :),</li>
	 *  <li><code>widther</code> - jQuery объект блока-потомка блока с историей (ему задаем фиксированные размеры при анимации),</li>
	 *  <li><code>isPhotoHover</code> - флаг ховера на изображении (нужен для анимации линка),</li>
	 *  <li><code>isLinkHover</code> - флаг ховера на линке (нужен для анимации линка),</li>
	 *  <li><code>isVisible</code> - флаг видимости истори (тоже, оказывается, нужен для анимации линка).</li>
	 * </ul>
	 */
	var objects = {};

	/**
	 * Идентификатор видимой истории.
	 */
	var curId = '';

	/**
	 * Горизонтальный (<code>horiz</code>) и вертикальный (<code>vert</code>) отступы блока <code>widther</code>.
	 */
	var widtherPaddings = {};

	/**
	 * Максимальный отступ сверху у линка (в раскрытом состоянии).
	 * @type {Number}
	 */
	var maxLinkPadding;

	$(function() {
		/** @type {jQuery} */
		var root = $('#content .main .inner');
		/** @type {jQuery} */
		var stories = root.find('.left-story, .right-story');

		root.find('.left, .right').each(function(index) {
			/** @type {String} */
			var id = getId($(this).attr('id'));

			// Заполняем наш главный объект блоками и переменными.
			objects[id] = {
				photo: $(this),
				story: stories.filter('#' + prefixes.story + id),
				isPhotoHover: false,
				isLinkHover: false,
				isVisible: false
			};
			objects[id].widther = objects[id].story.find('.widther');
			objects[id].link = objects[id].photo.find('.more');

			// Один раз вычисляем отступы.
			if (!index) {
				widtherPaddings = {
					horiz: parseInt(objects[id].widther.css('padding-left')) + parseInt(objects[id].widther.css('padding-right')),
					vert: parseInt(objects[id].widther.css('padding-top')) + parseInt(objects[id].widther.css('padding-bottom'))
				};
				maxLinkPadding = parseInt(objects[id].link.css('padding-top'));
			}

			// Обнуляем размеры блоков с историями, чтобы не было косяков при первом открытии.
			objects[id].story.css({
				height: 0,
				width: 0
			});

			// С запозданием скрываем линки, чтоб юзер их успел заметить.
			setTimeout(function() {
				hideLink(id);
			}, 2500);

			// Вешаем события на клики по линками и ховеры.
			objects[id].link.click(function(e) {
				onClick(id);
				e.stopPropagation();
			});
			objects[id].photo.click(function(e) {
				e.stopPropagation();
			});
			objects[id].story.click(function(e) {
				e.stopPropagation();
			});
			objects[id].photo.hover(function() {
				objects[id].isPhotoHover = true;
				showLink(id);
			}, function() {
				objects[id].isPhotoHover = false;
				hideLink(id);
			});
			objects[id].link.hover(function() {
				objects[id].isLinkHover = true;
				showLink(id);
			}, function() {
				objects[id].isLinkHover = false;
				hideLink(id);
			});
			$('body').click(function() {
				if (curId) {
					onClick(curId);
				}
			});
		});
	});

	/**
	 * Отрабатывает клик по линку.
	 * @param {String} id Идентификатор истории.
	 */
	function onClick(id) {
		// Останавливаем анимацию для блока, не важно, открывается он или закрывается.
		jTweener.removeTween(objects[id].story);

		if (curId == id) {
			// Если блок открыт, надо его просто закрыть.
			hide(id);
		} else {
			// Если блок закрыт, надо сначала закрыть открытый блок и сразу же открывать нужный.
			if (curId) {
				// Остановка анимации не сработает, потому что юзеру понадобилось кликнуть по другому блоку.
				// Остановим анимацию для открытого блока здесь и обнулим ему <code>z-index</code>.
				jTweener.removeTween(objects[curId].story);
				objects[curId].story.css('z-index', '');

				hide(curId);
			}

			show(id);
		}
	}

	/**
	 * Анимирует показ блока с историей.
	 * @param {String} id Идентификатор истории.
	 */
	function show(id) {
		// Именно здесь определяется новый текущий блок. Дальше нельзя, иначе будут косяки.
		curId = id;
		// И он перестает быть невидимым, ведь начинается анимация.
		objects[id].isVisible = true;
		showLink(id);

		/** @type {jQuery} */
		var storyBlock = objects[id].story;
		/** @type {Number} */
		var startHeight = storyBlock.height();
		/** @type {Number} */
		var startWidth = storyBlock.width();
		/** @type {Number} */
		var linkHeight = objects[id].link.outerHeight();
		/** @type {Number} */
		var linkWidth = objects[id].link.outerWidth();

		// Если размеры блока истории меньше размера блока линка, надо подогнать.
		if (linkHeight > startHeight) {
			startHeight = linkHeight;
		}
		if (linkWidth > startWidth) {
			startWidth = linkWidth;
		}

		// Вычисляем конечные размеры, до которых будем анимировать.
		// {{{
		storyBlock.css({
			//visibility: 'hidden',
			display: 'block',
			width: '',
			height: '',
			zIndex: 2
		});

		/** @type {Number} */
		var finishHeight = storyBlock.outerHeight();
		/** @type {Number} */
		var finishWidth = storyBlock.outerWidth();

		objects[id].widther.css({
			height: finishHeight
		});
		storyBlock.css({
			visibility: '',
			width: startWidth,
			height: startHeight
		});
		// }}}

		// Показываем другой текст у линка.
		objects[id].link.addClass('less').removeClass('once');

		jTweener.addTween(storyBlock, {
			height: finishHeight,
			width: finishWidth,
			time: 1,
			onComplete: function() {
				// Возвращаем все, как было.
				storyBlock.css({
					height: '',
					width: '',
					zIndex: ''
				});
				objects[id].widther.css({
					height: '',
					width: ''
				});
			}
		});
	}

	/**
	 * Анимирует скрытие блока с историей.
	 * @param {String} id Идентификатор истории.
	 */
	function hide(id) {
		// Именно здесь определяется новый текущий блок. Дальше нельзя, иначе будут косяки.
		curId = '';

		/** @type {jQuery} */
		var storyBlock = objects[id].story;
		/** @type {Number} */
		var startHeight = storyBlock.height();
		/** @type {Number} */
		var startWidth = storyBlock.width();

		// Вычисляем полные размеры блока с историей (нужно, чтоб текст не прыгал).
		// {{{
		storyBlock.css({
			visibility: 'hidden',
			display: 'block',
			width: '',
			height: ''
		});

		var fullHeight = storyBlock.height();
		var fullWidth = storyBlock.width();

		objects[id].widther.css({
			height: fullHeight
		});
		// }}}

		storyBlock.css({
			visibility: '',
			width: startWidth,
			height: startHeight
		});

		/** @type {Number} */
		var linkHeight = objects[id].link.outerHeight();
		/** @type {Number} */
		var linkWidth = objects[id].link.outerWidth();
		/** @type {Number} */
		var finishHeight = linkHeight;
		/** @type {Number} */
		var finishWidth = linkWidth;

		jTweener.addTween(storyBlock, {
			height: finishHeight,
			width: finishWidth,
			transition: 'easeInCubic',
			time: 0.5,
			onComplete: function() {
				storyBlock.css({
					display: 'none'
				});
				// Меняем текст у линка.
				objects[id].link.addClass('once').removeClass('less');
				// Вот теперь история становится невидимой.
				objects[id].isVisible = false;
				hideLink(id);
			}
		});
	}

	/**
	 * Анимирует показ линка.
	 * @param {String} id Идентификатор истории.
	 */
	function showLink(id) {
		/** @type {jQuery} */
		var link = objects[id].link;
		/** @type {Number} */
		var curPadding = parseInt(link.css('padding-top'));

		// Если линк уже показан или его не надо показывать, уходим.
		if (curPadding >= maxLinkPadding) {
			return;
		}
		if (!objects[id].isPhotoHover && !objects[id].isLinkHover && !objects[id].isVisible) {
			return;
		}

		jTweener.removeTween(link);
		jTweener.addTween(link, {
			paddingTop: maxLinkPadding,
			time: 0.5
		});
	}

	/**
	 * Анимирует скрытие линка.
	 * @param {String} id Идентификатор истории.
	 */
	function hideLink(id) {
		/** @type {jQuery} */
		var link = objects[id].link;
		/** @type {Number} */
		var curPadding = parseInt(link.css('padding-top'));
		/** @type {Number} */
		var height = link.height();

		var diff = 15;

		// Если линк уже скрыт или его не надо скрывать, уходим.
		if (curPadding <= maxLinkPadding - height - diff) {
			return;
		}
		if (objects[id].isPhotoHover || objects[id].isLinkHover || objects[id].isVisible) {
			return;
		}

		jTweener.removeTween(link);
		jTweener.addTween(link, {
			paddingTop: maxLinkPadding - height - diff,
			time: 0.5
		});
	}

	/**
	 * Возвращает идентификатор статьи по идентификатору html блока.
	 * @param {String} fullId Идентификатор html блока.
	 * @return {String} Идентификатор статьи или false, если кто-то облажался.
	 */
	function getId(fullId) {
		for (var type in prefixes) {
			if (prefixes[type] == fullId.substr(0, prefixes[type].length)) {
				return fullId.substr(prefixes[type].length);
			}
		}

		return false;
	}
})();