/*
var images = [
	[
		{ file: 'medium_1234.jpg', size: 300 },
		{ file: 'large_1234.jpg', size: 800 },
		{ file: 'large2_1234.jpg', size: 1280 },
		{ file: 'large3_1234.jpg', size: 2048 }
	],
	[
		{ file: 'medium_4321.jpg', size: 300 },
		{ file: 'large_4321.jpg', size: 800 },
		{ file: 'large2_4321.jpg', size: 1280 },
		{ file: 'large3_4321.jpg', size: 2048 }
	]
];

this.load(images);
*/

var Zoomer = {
	parent: '#zoomContent',
	img: '#zoomContent img',
	
	fadeDuration: 700,

	currentImage: 0,
	previousImage: 0,
	images: [],

	imageWidth: 0,
	imageHeight: 0,
	imageCenterX: 0,
	imageCenterY: 0,

	// The current x,y position in focus at imageCenterX/Y
	activeCenterX: 0,
	activeCenterY: 0,

	parentWidth: 0,
	parentHeight: 0,
	contentCenterX: 0,
	contentCenterY: 0,

	zoomLevel: 0,

	// Track zooming, reseting, and image swapping to prevent animated chaos
	changing: false,

	minX: 0,
	maxX: 0,
	minY: 0,
	maxY: 0,
	
	offsetLeft: 0,
	offsetTop: 0,
	
	// Used if image height is less than the parent containers height
	topCenterOffset: 0,

	/*
	$.animate() executes the callback function before the
	animation occurs, so a timer executes the necessary
	commands after X seconds. X = animation length.
	*/
	_hackTimer: '',
	
	load: function(images, index, debug) {
		if(index != undefined && index > this.currentImage)
		{
			var i = index;
			this.currentImage = index;
		}
		else
		{
			var i = this.currentImage;
		}

		this.images = images;

		this.parentWidth = $(this.parent).width();
		this.parentHeight = $(this.parent).height();
		this.contentCenterX = $(this.parent).width() / 2;
		this.contentCenterY = $(this.parent).height() / 2;
		
		this.fixImages();

		this.reset();
		$(this.img).css('top', this.topCenterOffset +'px');

		if(debug)
		{
			this.debug();
		}
	},

	reset: function() {
		$('#zoomIn').removeClass('inactive').addClass('active');
		$('#zoomReset, #zoomOut').removeClass('active').addClass('inactive');

		this.zoomLevel = 0;
		this.changing = false;
		this.imageWidth = this.images[this.currentImage][0].width;
		this.imageHeight = this.images[this.currentImage][0].height;
		
		this.minX = 0;
		this.maxX = 0;
		this.minY = 0;
		this.maxY = 0;
		
		this.offsetLeft = 0;
		this.offsetTop = 0;
		
		this.topCenterOffset = ($(this.parent).height() - this.images[this.currentImage][0].height) / 2;
		
		this.calculateImageCenter();
	},
	
	fixImages: function() {
		for(var i in this.images)
		{
			var percentage = 1;
			
			if(this.images[i][0].width >= this.images[i][0].height)
				percentage = ($(this.parent).width() / this.images[i][0].width);
			else if(this.images[i][0].width < this.images[i][0].height)
				percentage = ($(this.parent).height() / this.images[i][0].height);
			
			if(this.images[i][0].width > $(this.parent).width())
				this.images[i][0].width *= percentage;
			
			if(this.images[i][0].height > $(this.parent).height())
				this.images[i][0].height *= percentage;	
		}
	},
	
	changeImage: function(i, thumb) {
		if(this.images[i] != undefined)
		{
			if(i == this.currentImage || this.changing)
			{
				return;
			}
			
			$('img.selected').removeClass('selected');
			$(thumb).addClass('selected');
			
			this.changing = true;
			
			this.previousImage = this.currentImage;
			this.currentImage = i;
			
			$(this.img).draggable('destroy').animate({
				width: Zoomer.images[Zoomer.previousImage][0].width + 'px',
				height: Zoomer.images[Zoomer.previousImage][0].height + 'px',
				left: 0,
				top: 0 + Zoomer.topCenterOffset
			},{
				queue: false,
				duration: Zoomer.fadeDuration
			}).fadeOut(Zoomer.fadeDuration, function() {
				$(this).css({
					width: Zoomer.images[Zoomer.currentImage][0].width + 'px',
					height: Zoomer.images[Zoomer.currentImage][0].height + 'px'
				});
			});
			
			this._hackTimer = setTimeout(function() {
				Zoomer.reset();
				
				//$(Zoomer.img).attr('src', Zoomer.images[i][0].file);
				
				$(Zoomer.img).fadeOut('medium', function() {
					$('<img src="' + Zoomer.images[i][0].file + '" />').css('display', 'none').load(function() {
						$(Zoomer.img).css('top', Zoomer.topCenterOffset).attr('src', this.src).fadeIn(function() {
							Zoomer.changing = false;
						});
					});
				});
			}, Zoomer.fadeDuration);
		}
	},

	debug: function() {
		this.calculateImageCenter();

		if($('#zoomDebug')[0] == undefined)
		{
			$('#zoomContainer').after($('<div id="zoomDebug" style="position: absolute; right: 0;"></div>'));
		}

		$('#zoomDebug').html(
			'Zoom Level: ' + Zoomer.zoomLevel + '<br />' +
			'Width: ' + $(Zoomer.img).get(0).offsetWidth + '<br />' +
			'Height: ' + $(Zoomer.img).get(0).offsetHeight + '<br />' +
			'Left Offset: ' + $(Zoomer.img).get(0).offsetLeft + '<br />' +
			'Top Offset: ' + $(Zoomer.img).get(0).offsetTop + '<br />' +
			'Top Center Offset: ' + Zoomer.topCenterOffset + '<br />' +
			'Parent Offset: ' + $(Zoomer.parent).get(0).offsetLeft + ', ' + $(Zoomer.parent).get(0).offsetTop + '<br />' +
			'Container Center: ' + Zoomer.contentCenterX + ', ' + Zoomer.contentCenterY + '<br />' +
			'Image Center: ' + Zoomer.imageCenterX + ', ' + Zoomer.imageCenterY + '<br />' +
			'Active Center: ' + Zoomer.activeCenterX + ', ' + Zoomer.activeCenterY + '<br />' +
			'X Min,Max: ' + Zoomer.minX + ', ' + Zoomer.maxX + '<br />' +
			'Y Min,Max: ' + Zoomer.minY + ', ' + Zoomer.maxY + '<br />' +
			'Zoom Offset: ' + Zoomer.offsetLeft + ', ' + Zoomer.offsetTop + '<br />' +
			'Date: ' + Date()
		);

		setTimeout('Zoomer.debug()', 1000);
	},

	calculateImageCenter: function() {
		this.imageCenterX = Math.round(($(this.img).width() / 2) + $(this.img).get(0).offsetLeft);
		this.imageCenterY = Math.round(($(this.img).height() / 2) + $(this.img).get(0).offsetTop);
		
		this.activeCenterX = Math.round((this.imageCenterX - this.contentCenterX) - ($(this.img).width() / 2));
		this.activeCenterY = Math.round((this.imageCenterY - this.contentCenterY) - ($(this.img).height() / 2));

		if(this.activeCenterX < 0)
			this.activeCenterX *= -1;

		if(this.activeCenterY < 0)
			this.activeCenterY *= -1;
	},

	zoomReset: function(func)
	{
		if(this.changing)
		{
			return;
		}
		
		this.changing = true;
		
		fadeDuration = Zoomer.fadeDuration * (Zoomer.zoomLevel > 0 ? Zoomer.zoomLevel / 2 : 1);
		
		$(this.img).animate({
			width: Zoomer.images[Zoomer.currentImage][0].width + 'px',
			height: Zoomer.images[Zoomer.currentImage][0].height + 'px',
			left: 0,
			top: 0 + this.topCenterOffset
		},{
			queue: false,
			duration: fadeDuration > 700 ? fadeDuration : Zoomer.fadeDuration
		}).draggable('destroy');

		this._hackTimer = setTimeout(function() {
			Zoomer.reset();
			$(Zoomer.img).attr('src', Zoomer.images[Zoomer.currentImage][0].file);
			Zoomer.offsetLeft = Zoomer.offsetTop = Zoomer.minX = Zoomer.maxX = Zoomer.minY = Zoomer.maxY = 0;
		}, Zoomer.fadeDuration);
	},

	zoomIn: function()
	{
		if(this.zoomLevel < (this.images[this.currentImage].length - 1))
		{
			if(this.changing)
			{
				return;
			}

			this.changing = true;
			this.zoomLevel++;

			var imageSizeW = this.images[this.currentImage][this.zoomLevel].width;
			var imageSizeH = this.images[this.currentImage][this.zoomLevel].height;
			this.offsetLeft = Math.round(((this.activeCenterX / this.images[this.currentImage][(this.zoomLevel - 1)].width) * imageSizeW) - ($(this.parent).width() / 2)) * -1;
			this.offsetTop = Math.round(((this.activeCenterY / this.images[this.currentImage][(this.zoomLevel - 1)].height) * imageSizeH) - ($(this.parent).height() / 2)) * -1;

			this.minX = Math.round((imageSizeW - (this.parentWidth + $(this.parent).get(0).offsetLeft + parseInt($(this.parent).css('border-left-width'))))) * -1;
			this.maxX = $(this.parent).get(0).offsetLeft + parseInt($(this.parent).css('border-left-width'));
			this.minY = Math.round((imageSizeH - (this.parentHeight + $(this.parent).get(0).offsetTop + parseInt($(this.parent).css('border-top-width'))))) * -1;
			this.maxY = $(this.parent).get(0).offsetTop + parseInt($(this.parent).css('border-top-width'));

			$(this.img).animate({
				width: imageSizeW + 'px',
				height: imageSizeH + 'px',
				left: Zoomer.offsetLeft + 'px',
				top: Zoomer.offsetTop + 'px'
			},{
				queue: false,
				duration: Zoomer.fadeDuration
			}).draggable('destroy');

			this._hackTimer = setTimeout(function() {
				$(Zoomer.img).draggable({
					stop: function() { Zoomer.calculateImageCenter(); },
					containment: [Zoomer.minX, Zoomer.minY, Zoomer.maxX, Zoomer.maxY]
				});

				Zoomer.changing = false;
				Zoomer.calculateImageCenter();
				$('#zoomReset, #zoomOut').removeClass('inactive').addClass('active');

				// Maximum zoom has been reached
				if(Zoomer.zoomLevel == (Zoomer.images[Zoomer.currentImage].length - 1))
				{
					$('#zoomIn').removeClass('active').addClass('inactive');
				}

				$('<img>').attr('src', Zoomer.images[Zoomer.currentImage][Zoomer.zoomLevel].file).load(function() {
					$(Zoomer.img).attr('src', this.src);
				});
			}, Zoomer.fadeDuration);
		}
	},

	zoomOut: function()
	{
		if(this.zoomLevel > 0)
		{
			if(this.changing)
			{
				return;
			}

			if(this.zoomLevel == 1)
			{
				this.zoomReset();
				return;
			}

			this.changing = true;
			this.zoomLevel--;

			var imageSizeW = this.images[this.currentImage][this.zoomLevel].width;
			var imageSizeH = this.images[this.currentImage][this.zoomLevel].height;
			this.offsetLeft = Math.round(((this.activeCenterX / this.images[this.currentImage][(this.zoomLevel + 1)].width) * imageSizeW) - ($(this.parent).width() / 2)) * -1;
			this.offsetTop = Math.round(((this.activeCenterY / this.images[this.currentImage][(this.zoomLevel + 1)].height) * imageSizeH) - ($(this.parent).height() / 2)) * -1;

			this.minX = Math.round((imageSizeW - (this.parentWidth + $(this.parent).get(0).offsetLeft + parseInt($(this.parent).css('border-left-width'))))) * -1;
			this.maxX = $(this.parent).get(0).offsetLeft + parseInt($(this.parent).css('border-left-width'));
			this.minY = Math.round((imageSizeH - (this.parentHeight + $(this.parent).get(0).offsetTop + parseInt($(this.parent).css('border-top-width'))))) * -1;
			this.maxY = $(this.parent).get(0).offsetTop + parseInt($(this.parent).css('border-top-width'));

			/*
			// Left Offset correction
			if(this.offsetLeft < this.minX && $(this.img).get(0).offsetLeft < 0)
			{
				this.offsetLeft -= (this.offsetLeft - this.minX);
			}

			if(this.offsetLeft > 0)
			{
				this.offsetLeft = 0;
			}

			// Top Offset correction
			if(this.offsetTop < this.minY && $(this.img).get(0).offsetTop < 0)
			{
				this.offsetTop -= (this.offsetTop - this.minY);
			}

			if(this.offsetTop > 0)
			{
				this.offsetTop = 0;
			}
			*/

			var centeredMarginX = ((imageSizeW / 2) - (this.parentWidth / 2)) * 2;
			var centeredMarginY = ((imageSizeH / 2) - (this.parentHeight / 2)) * 2;

			// Left Offset Correction
			var tmpOffsetLeft = this.offsetLeft;

			if(tmpOffsetLeft < 0)
			{
				tmpOffsetLeft *= -1;
			}

			if(tmpOffsetLeft > centeredMarginX)
			{
				this.offsetLeft = this.offsetLeft < 0 ? this.offsetLeft + (tmpOffsetLeft - centeredMarginX) : this.offsetLeft - (tmpOffsetLeft - centeredMarginX);
			}

			if(this.offsetLeft > 0)
			{
				this.offsetLeft = 0;
			}

			// Right Offset Correction
			var tmpOffsetTop = this.offsetTop;

			if(tmpOffsetTop < 0)
			{
				tmpOffsetTop *= -1;
			}

			if(tmpOffsetTop > centeredMarginY)
			{
				this.offsetTop = this.offsetTop < 0 ? this.offsetTop + (tmpOffsetTop - centeredMarginY) : this.offsetTop - (tmpOffsetTop - centeredMarginY);
			}

			if(this.offsetTop > 0)
			{
				this.offsetTop = 0;
			}

			$(this.img).animate({
				width: imageSizeW + 'px',
				height: imageSizeH + 'px',
				left: Zoomer.offsetLeft + 'px',
				top: Zoomer.offsetTop + 'px'
			},{
				queue: false,
				duration: Zoomer.fadeDuration
			}).draggable('destroy');

			
			this._hackTimer = setTimeout(function() {
				Zoomer.changing = false;
				Zoomer.calculateImageCenter();
				$(Zoomer.img).attr('src', Zoomer.images[Zoomer.currentImage][Zoomer.zoomLevel].file).draggable({
					stop: function() { Zoomer.calculateImageCenter(); },
					containment: [Zoomer.minX, Zoomer.minY, Zoomer.maxX, Zoomer.maxY]
				});

				$('#zoomIn').removeClass('inactive').addClass('active');
			}, Zoomer.fadeDuration);
		}
	}
};