﻿(function() {
	var delegate = Function.createDelegate;

	var preloadImages = function(url1, url2, callback) {
		var loadCount = 0;

		var img1 = new Image();
		img1.onload = onLoadCallback;
		img1.src = url1;

		var img2 = new Image();
		img2.onload = onLoadCallback;
		img2.src = url2;

		function onLoadCallback() {
			if (++loadCount > 1) {
				callback(img1, img2);
			}
		};
	};

	ZoomBase = function(zoomItems, o) {
		var defaults = {};
		this.options = $.extend({}, defaults, o || {});
		this.zoomItems = $.isArray(zoomItems) ? zoomItems : new Array();
		this.enlargedImage = this.thumbnailImage = null;
		this.self = $(this);
		this.setup();
	};
	ZoomBase.prototype.extend = $.extend;
	ZoomBase.prototype.extend({
		setup: function() {
			this.viewPort = $('<div></div>')
                .addClass('zoom-viewport')
                .css({ 'position': 'absolute' });
			this.thumbnail = $('<div></div>')
                .addClass('zoom-thumbnail')
                .append(this.viewPort);
			this.canvasImage = $('<img></img>').css({ 'position': 'relative' });
			this.canvas = this.createCanvas(this.thumbnail, this.canvasImage);
			this.canvas.hide();
			$(document).find('body').prepend(this.canvas);
		},
		addZoomItem: function(i) {
			this.zoomItems.push(i);
		},
		removeZoomItem: function(id) {
			this.zoomItems = $.grep(this.zoomItems, function(item) { return item.id != id; });
		},
		calculateSizes: function() {
			var wWidth = this.canvas.width();
			var wHeight = this.canvas.height();
			var tbh = this.thumbnailImage.height;
			var tbw = this.thumbnailImage.width;
			var eh = this.enlargedImage.height;
			var ew = this.enlargedImage.width;
			this.vpSize = { h: (wHeight * tbh) / eh, w: (wWidth * tbw) / ew };
			this.viewPort.height(this.vpSize.h);
			this.viewPort.width(this.vpSize.w);
			this.zoomScale = Math.max(eh / tbh, ew / tbw);
		},
		calculateViewPortValues: function() {
			var tboff = this.thumbnail.offset();
			this.vpCorr = { y: tboff.top + this.vpSize.h / 2, x: tboff.left + this.vpSize.w / 2 };
			this.vpPosMax = { t: this.thumbnailImage.height - this.vpSize.h, l: this.thumbnailImage.width - this.vpSize.w };
		},
		hasZoomItem: function(itemId) {
			return ($.grep(this.zoomItems, function(item) { return item.id == itemId; })).length > 0;
		},
		displayZoom: function(itemId) {
			var zoomItem = ($.grep(this.zoomItems, function(item) { return item.id == itemId; }))[0];
			if (typeof (zoomItem) == 'undefined'
                || typeof (zoomItem.enlargedUrl) == 'undefined'
                || typeof (zoomItem.thumbnailUrl) == 'undefined') {
				return;
			}
			this.self.trigger('preload.start');
			preloadImages(zoomItem.enlargedUrl, zoomItem.thumbnailUrl, delegate(this, function(enlImg, thmbImg) {
				this.self.trigger('preload.end');
				if (enlImg == null || thmbImg == null) {
					return;
				}
				this.enlargedImage = enlImg;
				this.thumbnailImage = thmbImg;
				this.onPreDisplayZoom();
				this.canvasImage
                    .attr('src', enlImg.src)
                    .css({
                    	'width': enlImg.width + 'px',
                    	'height': enlImg.height + 'px'
                    });
				this.thumbnail.css({
					'background-image': 'url(' + thmbImg.src + ')',
					'width': thmbImg.width + 'px',
					'height': thmbImg.height + 'px'
				});
				this.calculateSizes();
				this.thumbnail.mousemove(delegate(this, this.handleThumbnailMouseMove));
				this.self.trigger('display');
				this.canvas.show();
				this.onPostDisplayZoom();
				this.calculateViewPortValues();
				this.setView(0, 0);
			}));
		},
		hideZoom: function() {
			this.onPreHideZoom();
			this.canvas.hide();
			this.onPostHideZoom();
			this.self.trigger('hide');
		},
		handleThumbnailMouseMove: function(e) {
			this.setView(e.pageY - this.vpCorr.y, e.pageX - this.vpCorr.x);
		},
		setView: function(vpTopRaw, vpLeftRaw) {
			var vpTop = Math.min(Math.max(vpTopRaw, 0), this.vpPosMax.t);
			var vpLeft = Math.min(Math.max(vpLeftRaw, 0), this.vpPosMax.l);
			var ceil = $.browser.msie ? Math.ceil : function(i) { return i };
			this.viewPort.css({ 'top': ceil(vpTop) + 'px', 'left': ceil(vpLeft) + 'px' });
			this.canvasImage.css({ 'top': -vpTop * this.zoomScale + 'px', 'left': -vpLeft * this.zoomScale + 'px' });
		}
	});

	FullscreenZoom = function(zoomItems, o) {
		this.base = ZoomBase;
		var defaults = {
			infoHtml: ''
		};
		var options = $.extend({}, defaults, o || {});
		this.base(zoomItems, options);
	};
	$.extend(FullscreenZoom.prototype, ZoomBase.prototype, {
		createCanvas: function(thumbnail, canvasImage) {
			var info = $('<div></div>')
                .addClass('zoom-info')
                .html(this.options.infoHtml);
			var closeButton = $('<a class="zoom-close" href="javascript:void(0);">Close zoom</a>')
                .click(delegate(this, this.hideZoom));
			this.toolBox = $('<div></div>')
                .addClass('zoom-toolbox')
                .css({ 'z-index': '150', 'position': 'absolute' })
                .append(info)
                .append(thumbnail)
                .append(closeButton);
			this.toolBox.hide();
			$(document).find('body')
                .prepend(this.toolBox);
			return $('<div></div>')
                .addClass('zoom-canvas')
                .css({ 'z-index': '100',
                	'overflow': 'hidden',
                	'background-color': 'black',
                	'position': 'absolute',
                	'top': '0px',
                	'left': '0px'
                })
                .append(canvasImage)
                .append($('<div></div>')
                        .addClass('zoom-toolbox-bg')
                        .css({ 'z-index': '120', 'position': 'absolute' }));
		},
		onPreDisplayZoom: function() {
			var body = $('body');
			var html = $('html');
			this.overflow = {
				bodyX: body.css('overflow-x'),
				bodyY: body.css('overflow-y'),
				htmlX: html.css('overflow-x'),
				htmlY: html.css('overflow-y')
			};
			scroll(0, 0);
			$('body, html').css({ 'overflow-x': 'hidden', 'overflow-y': 'hidden' });
			$(window).bind('resize.zoom', delegate(this, delegate(this, function() {
				this.calculateSizes();
				this.calculateViewPortValues();
				var vpPos = this.viewPort.position();
				this.setView(vpPos.top, vpPos.left);
			})));
		},
		onPostDisplayZoom: function() {
			this.toolBox.show();
		},
		onPreHideZoom: function() {
			var ovf = this.overflow;
			if (this.overflow != null && typeof (this.overflow) != "undefined") {
				$('body').css({ 'overflow-x': ovf.bodyX, 'overflow-y': ovf.bodyY });
				$('html').css({ 'overflow-x': ovf.htmlX, 'overflow-y': ovf.htmlY });
			}			
			$(window).unbind('resize.zoom');
		},
		onPostHideZoom: function() {
			this.toolBox.hide();
		},
		calculateSizes: function() {
			var wnd = $(window);
			var wWidth = wnd.width();
			var wHeight = wnd.height();
			this.canvas.width(wWidth).height(wHeight);
			ZoomBase.prototype.calculateSizes.call(this);
		}
	});

	EmbeddedZoom = function(zoomItems) {
		this.base = ZoomBase;
		this.host = null;
		this.base(zoomItems);
		this.onPostDisplayZoom = this.onPreHideZoom = function() { };
	};
	$.extend(EmbeddedZoom.prototype, ZoomBase.prototype, {
		setHost: function(host) {
			this.host = $(host);
			this.canvas.width(this.host.width()).height(this.host.height());
		},
		createCanvas: function(thumbnail, canvasImage) {
			return $('<div></div>')
                .addClass('zoom-canvas-embedded')
                .css({ 'z-index': '90',
                	'overflow': 'hidden',
                	'background-color': 'black',
                	'position': 'absolute',
                	'top': '0px',
                	'bottom': '0px',
                	'left': '0px',
                	'right': '0px'
                })
                .append(canvasImage)
                .append(thumbnail);
		},
		onPreDisplayZoom: function() {
			this.host.append(this.canvas);
		},
		onPostHideZoom: function() {
			this.host.find('.zoom-canvas-embedded').remove();
		}
	});
})();
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();