/**
 * @author Vlad Yakovlev (red.scorpix@gmail.com)
 * @link www.scorpix.ru
 * @requires jQuery
 */
$(function() {

	function dndView(rootEl, touchEl, scaleEl) {
		var
			beforeEl = rootEl.find('.before'),
			afterEl = rootEl.find('.after'),
			beforeImgEl = beforeEl.find('img'),
			afterImgEl = afterEl.find('img'),
			runnerEl = scaleEl.find('.runner'),
			runnerTouchEl = scaleEl.find('.runner_touch'),
			filledTouchEl = scaleEl.find('.filled');

		var
			minWidth,
			minHeight,
			minImageWidth,
			minImageHeight,
			maxWidth,
			maxHeight,
			maxLeft,
			maxTop,
			startImgX,
			startImgY,
			startTouchLeft,
			curWidth,
			curHeight,
			curScale = 0.25;

		function init() {

			if (!minWidth) {
				minWidth = beforeEl.width();
				minHeight = beforeEl.height();
				maxWidth = beforeImgEl.attr('width');
				maxHeight = beforeImgEl.attr('height');
				curWidth = maxWidth;
				curHeight = maxHeight;

				if (maxWidth / maxHeight < minWidth / minHeight) {
					minImageWidth = minWidth;
					minImageHeight = Math.round(minWidth / maxWidth * maxHeight);
				} else {
					minImageHeight = minHeight;
					minImageWidth = Math.round(minHeight / maxHeight * maxWidth);
				}
			}

			var left = Math.round(curScale * scaleEl.width());
			updateImages(left);
			runnerEl.css('left', left);
			filledTouchEl.css('width', left);

			touchEl.mousedown(onDown);
			runnerTouchEl.mousedown(startRunnerDnd);
		}

		function pause() {
			touchEl.unbind('mousedown', onDown);
			runnerTouchEl.unbind('mousedown', startRunnerDnd);
		}

		function onDown(evt) {
			if (!rootEl.hasClass('selected')) return;

			maxLeft = curWidth - minWidth;
			maxTop = curHeight - minHeight;

			startDnd(evt);
		}

		/**
		 * @param {Event} evt
		 */
		function startRunnerDnd(evt) {
			evt.preventDefault();
			evt.stopPropagation();

			startTouchMouseLeft = parseInt(evt.pageX);
			startTouchLeft = Math.round(runnerTouchEl.offset().left);
			var left = startTouchMouseLeft - startTouchLeft;
			updateImages(left);
			runnerEl.css('left', left);
			filledTouchEl.css('width', left);

			$(document).mousemove(runnerDnd).mouseup(stopRunnerDnd);
		}

		/**
		 * @param {Event} evt
		 */
		function runnerDnd(evt) {
			evt.preventDefault();
			evt.stopPropagation();

			var mouseX = parseInt(evt.pageX);
			var left = mouseX - startTouchLeft;
			var width = scaleEl.width();

			if (0 > left) {
				left = 0;
			} else if (width < left) {
				left = width;
			}

			curScale = left / width;
			updateImages(left);
			runnerEl.css('left', left);
			filledTouchEl.css('width', left);
		}

		function updateImages(left) {
			var width = scaleEl.width();
			var oldWidth = curWidth;
			var oldHeight = curHeight;
			curWidth = Math.round(minImageWidth + (maxWidth - minImageWidth) * left / width);
			curHeight = Math.round(minImageHeight + (maxHeight - minImageHeight) * left / width);

			var oldImgXCenter = Math.round(-parseInt(beforeImgEl.css('left')) + minWidth / 2);
			var oldImgYCenter = Math.round(-parseInt(beforeImgEl.css('top')) + minHeight / 2);

			var curImgXCenter = Math.round(oldImgXCenter * curWidth / oldWidth);
			var curImgYCenter = Math.round(oldImgYCenter * curHeight / oldHeight);

			var imgLeft = curImgXCenter - Math.round(minWidth / 2);
			var imgTop = curImgYCenter - Math.round(minHeight / 2);

			beforeImgEl.css({
				height: curHeight,
				width: curWidth
			});
			afterImgEl.css({
				height: curHeight,
				width: curWidth
			});

			if (imgLeft > curWidth - minImageWidth) {
				imgLeft = curWidth - minImageWidth;
			} else if (0 > imgLeft) {
				imgLeft = 0;
			}
			if (imgTop > curHeight - minImageHeight) {
				imgTop = curHeight - minImageHeight;
			} else if (0 > imgTop) {
				imgTop = 0;
			}

			beforeImgEl.css('left', -imgLeft);
			afterImgEl.css('left', -imgLeft);
			beforeImgEl.css('top', -imgTop);
			afterImgEl.css('top', -imgTop);
		}

		/**
		 * @param {Event} evt
		 */
		function stopRunnerDnd(evt) {
			evt.preventDefault();
			evt.stopPropagation()

			$(document).unbind('mousemove', runnerDnd).unbind('mouseup', stopRunnerDnd);
		}

		/**
		 * @param {Event} evt
		 */
		function startDnd(evt) {
			evt.preventDefault();
			evt.stopPropagation();

			startImgX = parseInt(beforeImgEl.css('left'));
			startImgY = parseInt(beforeImgEl.css('top'));
			startMouseX = parseInt(evt.pageX);
			startMouseY = parseInt(evt.pageY);

			$(document).mousemove(dnd).mouseup(stopDnd);
		}

		/**
		 * @param {Event} evt
		 */
		function dnd(evt) {
			evt.preventDefault();
			evt.stopPropagation();

			var mouseX = parseInt(evt.pageX);
			var mouseY = parseInt(evt.pageY);

			var imgX = startImgX + (mouseX - startMouseX);
			var imgY = startImgY + (mouseY - startMouseY);

			if (0 < imgX) {
				imgX = 0;
			} else if (-maxLeft > imgX) {
				imgX = -maxLeft;
			}
			if (0 < imgY) {
				imgY = 0;
			} else if (-maxTop > imgY) {
				imgY = -maxTop;
			}

			beforeImgEl.css({
				left: imgX,
				top: imgY
			});
			afterImgEl.css({
				left: imgX,
				top: imgY
			});
		}

		/**
		 * @param {Event} evt
		 */
		function stopDnd(evt) {
			evt.preventDefault();
			evt.stopPropagation()

			$(document).unbind('mousemove', dnd).unbind('mouseup', stopDnd);
		}

		return {
			init: init,
			pause: pause
		};
	}

	var sectionEls = $('#content .retouching_example .example');
	var linkEls = $('#content .columns .example .pseudo');
	var touchEl = $('#content .retouching_example .touch');
	var exampleInfoEls = $('#content .example_info');
	var exampleSourceEls = $('#content .example_source');
	var dndViews = [];

	linkEls.each(function(index) {
		var linkEl = linkEls.eq(index);
		var sectionEl = sectionEls.eq(index);
		var exampleInfoEl = exampleInfoEls.eq(index);
		var exampleSourceEl = exampleSourceEls.eq(index);

		dndViews.push(dndView(sectionEl, touchEl, $('#content .retouching_example .scale')));

		linkEl.click(function() {
			if ($(this).hasClass('selected')) return;

			for (var i = 0; i < dndViews.length; i++) {
				dndViews[i].pause();
			}

			linkEls.filter('.selected').removeClass('selected');
			sectionEls.filter('.selected').removeClass('selected');
			exampleInfoEls.filter('.example_info_selected').removeClass('example_info_selected');
			exampleSourceEls.filter('.example_source_selected').removeClass('example_source_selected');
			linkEl.addClass('selected');
			sectionEl.addClass('selected');
			exampleInfoEl.addClass('example_info_selected');
			exampleSourceEl.addClass('example_source_selected');
			dndViews[index].init();
		});
	});

	dndViews[0].init();
});
