/**
 * @author Vlad Yakovlev (red.scorpix@gmail.com)
 * @link www.scorpix.ru
 * @requires jQuery
 * @requires jCommon
 * @version 0.1.1
 * @date 2010-02-18
 */

$(function() {

	if ($c.browser.msie && 6 >= parseInt($c.browser.version)) {
		$('#layout').css('zoom', 1);
	}

	function yoga(rootEl, itemEls) {
		rootEl = $(rootEl);
		itemEls = $(itemEls);

		var maxWidth = 400;
		var
			containerEl = $('<div class="yoga_container" />').prependTo(rootEl),
			links = $('#header .make_yoga .pseudo');
		var
			data = [],
			isAnimate = false,
			animateTime = 0.3,
			nsIn = 'yogaIn' + Math.random(),
			nsOut = 'yogaOut' + Math.random();

		init();

		jTweener.addNSAction({
			onComplete: function() {
				isAnimate = false;
				$('#layout').css('overflow', '');
				containerEl.css('height', '');

				itemEls.each(function(index) {
					data[index].el.css({
						left: '',
						position: '',
						top: ''
					});
				});

				if ($c.browser.msie && 6 >= parseInt($c.browser.version)) {
					$('#layout').css('zoom', 1);
				}
			}
		}, nsIn);
		jTweener.addNSAction({
			onComplete: function() {
				containerEl.addClass('hidden');
				itemEls.removeClass('hidden').css('visibility', '');

				itemEls.each(function(index) {
					data[index].el.css({
						left: '',
						position: '',
						top: ''
					});
				});

				isAnimate = false;
				$('#layout').css('overflow', '');

				if ($c.browser.msie && 6 >= parseInt($c.browser.version)) {
					$('#layout').css('zoom', 1);
				}
			}
		}, nsOut);

		links.click(function() {
			if (isAnimate) return;

			if ($(this).hasClass('make')) {
				animateIn();
				links.filter('.cancel').removeClass('hidden');
			} else {
				animateOut();
				links.filter('.make').removeClass('hidden');
			}

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

		function init() {

			containerEl.addClass('hidden');

			itemEls.each(function() {

				var
					el = $('<div class="yoga_item" />'),
					contentEl = $(this).clone().appendTo(el),
					deg = 90 * $c.random(-1, 1);

				el.appendTo(containerEl);

				contentEl.css({
					left: 0,
					position: 'absolute',
					top: 0
				});
				data.push({
					el: el,
					contentEl: contentEl,
					deg: deg
				});
			});
		}

		function animateIn() {

			isAnimate = true;

			containerEl.removeClass('hidden');
			var containerOffset = containerEl.offset();
			containerEl.css({
				left: -10000,
				position: 'absolute',
				top: -10000
			});

			itemEls.each(function(index) {
				var
					sourceEl = $(this),
					offset = sourceEl.offset(),
					sourceWidth = sourceEl.width(),
					sourceHeight = sourceEl.height(),
					sourceOuterWidth = sourceEl.outerWidth(),
					sourceOuterHeight = sourceEl.outerHeight(),
					width = maxWidth < sourceWidth ? maxWidth : sourceWidth;

				data[index].contentEl.css('width', width);
				width = data[index].contentEl.outerWidth();
				var height = data[index].contentEl.outerHeight();

				data[index].el.css('width', width);

				data[index].sourceLeft = Math.round(offset.left - containerOffset.left);
				data[index].sourceTop = Math.round(offset.top - containerOffset.top);
				data[index].sourceHeight = sourceHeight;
				data[index].sourceWidth = sourceWidth;
				data[index].sourceOuterHeight = sourceOuterHeight;
				data[index].sourceOuterWidth = sourceOuterWidth;
				data[index].height = height;
				data[index].width = width;
				data[index].rotateHeight = 0 == data[index].deg || $c.browser.msie ? height : width;
				data[index].rotateWidth = 0 == data[index].deg || $c.browser.msie ? width : height;

				$c.browser.msie ? ieRotate(data[index].el, data[index].deg, data[index].deg) : rotate(data[index].el, data[index].deg, data[index].deg);
				data[index].el.css({
					height: data[index].rotateHeight,
					width: data[index].rotateWidth
				});
			});

			containerEl.css('height', containerEl.height());

			itemEls.each(function(index) {
				var offset = data[index].el.position();
				data[index].left = Math.round(offset.left);
				data[index].top = Math.round(offset.top);
			});

			itemEls.each(function(index) {
				var
					el = data[index].el;

				el.css({
					height: data[index].sourceOuterHeight,
					left: data[index].sourceLeft,
					position: 'absolute',
					top: data[index].sourceTop,
					width: data[index].sourceOuterWidth
				});
				el.children().first().css({
					height: data[index].sourceHeight,
					left: $c.browser.msie ? 0 : '50%',
					marginLeft: $c.browser.msie ? 0 : -Math.round(data[index].sourceOuterWidth / 2),
					marginTop: $c.browser.msie ? 0 : -Math.round(data[index].sourceOuterHeight / 2),
					top: $c.browser.msie ? 0 : '50%',
					width: data[index].sourceWidth
				});
			});

			itemEls.addClass('hidden').css('visibility', 'hidden');
			containerEl.css({
				left: '',
				position: '',
				top: ''
			});

			$('#layout').css('overflow', 'hidden');

			itemEls.each(function(index) {

				var
					item = data[index],
					el = item.el,
					contentEl = el.children().first(),
					startMarginLeft = $c.browser.msie ? 0 : -Math.round(data[index].sourceOuterWidth / 2),
					startMarginTop = $c.browser.msie ? 0 : -Math.round(data[index].sourceOuterHeight / 2),
					endMarginLeft = $c.browser.msie ? 0 : -Math.round(data[index].width / 2),
					endMarginTop = $c.browser.msie ? 0 : -Math.round(data[index].height / 2);

				$t(el, {
					time: animateTime,
					transition: 'easeOutCubic',
					'namespace': nsIn,
					moveX: function(value) {
						el.css({
							left: item.sourceLeft + (item.left - item.sourceLeft) * value,
							height: item.sourceOuterHeight + (item.rotateHeight - item.sourceOuterHeight) * value,
							top: item.sourceTop + (item.top - item.sourceTop) * value,
							width: item.sourceWidth + (item.rotateWidth - item.sourceWidth) * value
						});
						contentEl.css({
							marginLeft: startMarginLeft + (endMarginLeft - startMarginLeft) * value,
							marginTop: startMarginTop + (endMarginTop - startMarginTop) * value,
							height: item.sourceHeight + (item.height - item.sourceHeight) * value,
							width: item.sourceWidth + (item.width - item.sourceWidth) * value
						});

						var curDeg = Math.round(value * item.deg);
						$c.browser.msie ? ieRotate(el, curDeg, item.deg) : rotate(el, curDeg, item.deg);
					}
				}).tween();
			});
		}

		function animateOut() {

			isAnimate = true;

			$('#layout').css('overflow', 'hidden');
			containerEl.css('position', 'absolute');
			itemEls.removeClass('hidden');

			var containerOffset = containerEl.offset();

			itemEls.each(function(index) {
				var
					sourceEl = $(this),
					offset = sourceEl.offset(),
					sourceWidth = sourceEl.outerWidth(),
					sourceHeight = sourceEl.outerHeight(),
					width = data[index].contentEl.width(),
					height = data[index].contentEl.height();

				data[index].left = Math.round(offset.left - containerOffset.left);
				data[index].top = Math.round(offset.top - containerOffset.top);
				data[index].height = sourceHeight;
				data[index].width = sourceWidth;
				data[index].sourceHeight = height;
				data[index].sourceWidth = width;
				data[index].rotateHeight = 0 == data[index].deg || $c.browser.msie ? height : width;
				data[index].rotateWidth = 0 == data[index].deg || $c.browser.msie ? width : height;

				var offset = data[index].el.position();
				data[index].sourceLeft = Math.round(offset.left);
				data[index].sourceTop = Math.round(offset.top);
			});

			itemEls.each(function(index) {
				var
					el = data[index].el;

				el.css({
					height: data[index].rotateHeight,
					left: data[index].sourceLeft,
					position: 'absolute',
					top: data[index].sourceTop,
					width: data[index].rotateWidth
				});
			});

			$('#layout').css('overflow', 'hidden');

			itemEls.each(function(index) {

				var
					item = data[index],
					el = item.el,
					contentEl = el.children().first(),
					endMarginLeft = $c.browser.msie ? 0 : -Math.round(data[index].width / 2),
					endMarginTop = $c.browser.msie ? 0 : -Math.round(data[index].height / 2),
					startMarginLeft = $c.browser.msie ? 0 : -Math.round(data[index].sourceWidth / 2),
					startMarginTop = $c.browser.msie ? 0 : -Math.round(data[index].sourceHeight / 2);

				$t(el, {
					time: animateTime,
					transition: 'easeInCubic',
					'namespace': nsOut,
					moveX: function(value) {
						el.css({
							left: item.sourceLeft + (item.left - item.sourceLeft) * value,
							height: item.rotateHeight + (item.height - item.rotateHeight) * value,
							top: item.sourceTop + (item.top - item.sourceTop) * value,
							width: item.rotateWidth + (item.width - item.rotateWidth) * value
						});
						contentEl.css({
							marginLeft: startMarginLeft + (endMarginLeft - startMarginLeft) * value,
							marginTop: startMarginTop + (endMarginTop - startMarginTop) * value,
							height: item.sourceHeight + (item.height - item.sourceHeight) * value,
							width: item.sourceWidth + (item.width - item.sourceWidth) * value
						});

						var curDeg = Math.round((1 - value) * item.deg);
						$c.browser.msie ? ieRotate(el, curDeg, item.deg) : rotate(el, curDeg, item.deg);
					}
				}).tween();
			});
		}

		function rotate(el, newDeg, sourceDeg) {
			if (0 == sourceDeg) return;

			var
				name = '',
				value = 'rotate(' + newDeg + 'deg)';

			if ($c.browser.mozilla) {
				name = '-moz-transform';
			} else if ($c.browser.opera) {
				name = '-o-transform';
			} else if ($c.browser.webkit) {
				name = '-webkit-transform';
			} else {
				return;
			}

			el.css(name, value);
		}

		function ieRotate(el, newDeg, sourceDeg) {
			if (0 == sourceDeg) return;

			el[0].style.filter = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand')";

			var
				rad = newDeg * (Math.PI * 2 / 360),
				costheta = Math.cos(rad),
				sintheta = Math.sin(rad),
				item = el[0].filters.item(0);

    	item.M11 = costheta;
    	item.M12 = -sintheta;
    	item.M21 = sintheta;
    	item.M22 = costheta;
		}
	}

	yoga('#content', '.navigation_item, .subnavigation_item, h1, .yoga');
});
