/**
 * @author Vlad Yakovlev (red.scorpix@gmail.com)
 * @link www.scorpix.ru
 * @requires jQuery
 * @requires jCommon
 * @requires jTweener
 */

/**
 * Галерея с показом больших фотографий.
 * @param {String|Element|jQuery} popupEl
 * @param {String|Element|Array[Element]|jQuery} previewsEls
 */
var Gallery = (function() {

	function galleryBlock(popupEl, previewsEls, linkEl) {

		var
			prevNs = 'gallery_prev',
			nextNs = 'gallery_next',
			prevTweenParams = { time: .6, namespace: prevNs },
			nextTweenParams = { time: .6, namespace: nextNs };

		var
			pictureEl = popupEl.find('.picture'),
			faderEl = popupEl.find('.fader'),
			closeEl = popupEl.find('.close'),
			popupPreviewsEl = popupEl.find('.previews');

		var info = [];
		var defaultCss = { left: '' };
		var popup;

		popupEl.appendTo('body');

		init();

		function init() {
			var curPicture = popupEl.find('.picture');
			curPicture.clone().appendTo(popupEl).addClass('prev_picture');
			curPicture.clone().appendTo(popupEl).addClass('next_picture');
			curPicture.clone().appendTo(popupEl).addClass('hid_picture');
			curPicture.addClass('cur_picture');

			previewsEls.each(function() {
				var
					el = $(this),
					image = el.find('img'),
					sizes = el.attr('title').split('x');

				info.push({
					src: el.attr('href'),
					description: image.attr('alt'),
					height: parseInt(sizes[1]),
					width: parseInt(sizes[0]),
					loaded: false
				});

				$('<ins />').appendTo(popupPreviewsEl);
			});

			jTweener.addNSAction({ onComplete: onPrevComplete }, prevNs);
			jTweener.addNSAction({ onComplete: onNextComplete }, nextNs);

			popupEl.find('.picture').click(function() {
				if (popupEl.hasClass('photo_popup_animate')) return;

				if ($(this).hasClass('prev_picture')) {
					prev();
				} else if ($(this).hasClass('next_picture')) {
					next();
				}
			});
			previewsEls.click(function() {
				change($(this).prevAll('a').length);

				return false;
			});
			linkEl.click(function() {
				setTimeout(function() {
					change(0);
				}, 1);
			});
			popupPreviewsEl.find('ins').click(function() {
				change($(this).prevAll('ins').length);

				return false;
			});
			popup = $c.popupBlock(popupEl, {
				close: closeEl,
				beforeHide: function() {
					previewsEls.filter('.selected').removeClass('selected');
				}
			});
			faderEl.click(function() {
				popup.hide();
			});

			loadImage(0);
			loadImage(1);
			loadImage(previewsEls.length - 1);
		}

		function change(index) {
			previewsEls.filter('.selected').removeClass('selected');
			previewsEls.eq(index).addClass('selected');
			popupPreviewsEl.find('.selected').removeClass('selected');
			popupPreviewsEl.find('ins').eq(index).addClass('visited').addClass('selected');

			var
				prevIndex = 0 <= index - 1 ? index - 1 : previewsEls.length - 1,
				nextIndex = previewsEls.length - 1 < index + 1 ? 0 : index + 1,
				indexes = [prevIndex, nextIndex, index];

			for (var i = 0; i < indexes.length; i++) {
				var elName;

				switch (i) {
					case 0: elName = 'prev_picture'; break;
					case 1: elName = 'next_picture'; break;
					case 2: elName = 'cur_picture'; break;
				}

				if ('prev_picture' == elName && prevIndex == previewsEls.length - 1) {
					popupEl.find('.' + elName).css('visibility', 'hidden');
				} else if ('next_picture' == elName && nextIndex == 0) {
					popupEl.find('.' + elName).css('visibility', 'hidden');
				} else {
					popupEl.find('.' + elName).css('visibility', '');
				}

				fillPicture(popupEl.find('.' + elName), indexes[i], indexes[i] == index);
			}

			loadImage(0 <= prevIndex - 1 ? prevIndex - 1 : previewsEls.length - 1);
			loadImage(previewsEls.length - 1 < nextIndex + 1 ? 0 : nextIndex + 1);
			popup.show();
		}

		function prev() {
			var
				selItem = previewsEls.filter('.selected'),
				index = selItem.prevAll('a').length,
				prevIndex = 0 <= index - 1 ? index - 1 : previewsEls.length - 1,
				nextIndex = previewsEls.length - 1 < index + 1 ? 0 : index + 1,
				rootOffset = popupEl.offset(),
				prevPicture = popupEl.find('.prev_picture'),
				prevOffset = prevPicture.offset(),
				nextPicture = popupEl.find('.next_picture'),
				nextOffset = nextPicture.offset(),
				curPicture = popupEl.find('.cur_picture'),
				curOffset = curPicture.offset(),
				hidPicture = popupEl.find('.hid_picture'),
				hidIndex = 0 <= prevIndex - 1 ? prevIndex - 1 : previewsEls.length - 1;

			selItem.prev('a').addClass('selected');
			selItem.removeClass('selected');
			popupPreviewsEl.find('.selected').removeClass('selected');
			popupPreviewsEl.find('ins').eq(prevIndex).addClass('visited').addClass('selected');

			hidPicture.css('visibility', previewsEls.length - 1 == hidIndex ? 'hidden' : '');

			loadImage(0 <= prevIndex - 1 ? prevIndex - 1 : previewsEls.length - 1);
			prevPicture.css({ left: prevOffset.left - rootOffset.left });
			curPicture.css({ left: curOffset.left - rootOffset.left });
			nextPicture.css({ left: nextOffset.left - rootOffset.left });
			fillPicture(hidPicture, hidIndex);
			hidPicture.css({ left: -1000 });

			popupEl.addClass('photo_popup_animate');
			$t(prevPicture, prevTweenParams).tween({ left: curOffset.left - rootOffset.left + Math.round((curPicture.width() - prevPicture.width()) / 2) });
			$t(curPicture, prevTweenParams).tween({ left: nextOffset.left - rootOffset.left });
			$t(nextPicture, prevTweenParams).tween({ left: nextOffset.left - rootOffset.left + 1000 });
			$t(hidPicture, prevTweenParams).tween({ left: prevOffset.left - rootOffset.left + prevPicture.width() - hidPicture.width() });
		}

		function next() {
			var
				selItem = previewsEls.filter('.selected'),
				index = selItem.prevAll('a').length,
				prevIndex = 0 <= index - 1 ? index - 1 : previewsEls.length - 1,
				nextIndex = previewsEls.length - 1 < index + 1 ? 0 : index + 1,
				rootOffset = popupEl.offset(),
				prevPicture = popupEl.find('.prev_picture'),
				prevOffset = prevPicture.offset(),
				nextPicture = popupEl.find('.next_picture'),
				nextOffset = nextPicture.offset(),
				curPicture = popupEl.find('.cur_picture'),
				curOffset = curPicture.offset(),
				hidPicture = popupEl.find('.hid_picture'),
				hidIndex = previewsEls.length - 1 < nextIndex + 1 ? 0 : nextIndex + 1;

			selItem.next('a').addClass('selected');
			selItem.removeClass('selected');
			popupPreviewsEl.find('.selected').removeClass('selected');
			popupPreviewsEl.find('ins').eq(nextIndex).addClass('visited').addClass('selected');

			hidPicture.css('visibility', 0 == hidIndex ? 'hidden' : '');

			loadImage(previewsEls.length - 1 < nextIndex + 1 ? 0 : nextIndex + 1);
			prevPicture.css({ left: prevOffset.left - rootOffset.left });
			curPicture.css({ left: curOffset.left - rootOffset.left });
			nextPicture.css({ left: nextOffset.left - rootOffset.left });
			fillPicture(hidPicture, hidIndex);
			hidPicture.css({ left: nextOffset.left - rootOffset.left + 1000 });

			popupEl.addClass('photo_popup_animate');
			$t(prevPicture, nextTweenParams).tween({ left: -1000 });
			$t(curPicture, nextTweenParams).tween({ left: prevOffset.left - rootOffset.left + prevPicture.width() - curPicture.width() });
			$t(nextPicture, nextTweenParams).tween({ left: curOffset.left - rootOffset.left + Math.round((curPicture.width() - nextPicture.width()) / 2) });
			$t(hidPicture, nextTweenParams).tween({ left: nextOffset.left - rootOffset.left });
		}

		function onPrevComplete() {
			var
				prevPicture = popupEl.find('.prev_picture'),
				nextPicture = popupEl.find('.next_picture'),
				curPicture = popupEl.find('.cur_picture'),
				hidPicture = popupEl.find('.hid_picture');

			prevPicture.css(defaultCss).removeClass('prev_picture').addClass('cur_picture').css('left', -Math.round(prevPicture.find('img').attr('width') / 2));
			nextPicture.css(defaultCss).removeClass('next_picture').addClass('hid_picture');
			curPicture.css(defaultCss).removeClass('cur_picture').addClass('next_picture');
			hidPicture.css(defaultCss).removeClass('hid_picture').addClass('prev_picture');
			popupEl.removeClass('photo_popup_animate');
		}

		function onNextComplete() {
			var
				prevPicture = popupEl.find('.prev_picture'),
				nextPicture = popupEl.find('.next_picture'),
				curPicture = popupEl.find('.cur_picture'),
				hidPicture = popupEl.find('.hid_picture');

			prevPicture.css(defaultCss).removeClass('prev_picture').addClass('hid_picture');
			nextPicture.css(defaultCss).removeClass('next_picture').addClass('cur_picture').css('left', -Math.round(nextPicture.find('img').attr('width') / 2));
			curPicture.css(defaultCss).removeClass('cur_picture').addClass('prev_picture');
			hidPicture.css(defaultCss).removeClass('hid_picture').addClass('next_picture');
			popupEl.removeClass('photo_popup_animate');
		}

		function fillPicture(el, index, isCurrent) {
			el.css('left', isCurrent ? -Math.round(info[index].width / 2) : '')
				.find('img').attr({
					alt: info[index].description,
					src: info[index].src,
					height: info[index].height,
					width: info[index].width
				}).end()
				.find('.description').text(info[index].description);
			loadImage(index);
		}

		function loadImage(index) {
			if (info[index].loaded) return;

			var image = new Image();
			image.onload = function() {
				info[index].loaded = true;
			};
			image.src = info[index].src;
		}
	}

	return function(popupEl, previewsEls, linkEl) {
		galleryBlock($(popupEl), $(previewsEls), $(linkEl));
	}
})();