var UIZoomLigth =  Class.create();
UIZoomLigth.prototype = {
	initialize: function(container, carousel, options)
	{
		this.carousel = carousel;
		this.options = {
			animate: false,
			prefix : 'ScrollImage',
			imageID: 'ZoomImage',
			images : []
		};
		Object.extend(this.options,options);
		this.element = $(container);
		this.image = $(this.options.imageID);
		this.lhBox = $$("a[class*=ZoomEnlarge]")[0];
		this.lhBoxN= $$("span[class*=ZoomEnlarge]")[0];
		this.carousel.element.observe('carousel:imageChange', (function(event) { event.stop(); this.setImage(this.getCurrentDetail()); }).bindAsEventListener(this));
		this.updateLoupe();
	},

	setImage: function(src)
	{
		if (this.image.src.indexOf(src) != -1) return;
		this.image.src = src;
		if (this.lhBox) this.lhBox.href = this.getCurrentZoom();
		this.updateLoupe();
	},

	updateLoupe: function(reset)
	{
		try
		{
			if (this.isZoom())
			{
				this.lhBox.show();
				this.lhBoxN.hide();
			} else
			{
				this.lhBox.hide();
				this.lhBoxN.show();
			}
		} catch(e) {};
	},

	getCurrentID: function() {return this.carousel.getCurrent().identify().replace(this.options.prefix,'');},
	getCurrentDetail: function() {return this.options.images[this.getCurrentID()].detail;},
	getCurrentZoom: function() {return this.options.images[this.getCurrentID()].zoom;},
	isZoom: function() {return this.options.images[this.getCurrentID()].zoom!='#';},
	_changeImage: function() {this.setCurrentID(this.carousel.getCurrent().identify());}
}

var UIZoom =  Class.create();
UIZoom.prototype = {
	initialize: function(container, carousel, options)
	{
		this.carousel = carousel;
		this.options = {
			animate: false,
			prefix : 'ScrollImage',
			imageID: 'ZoomImage',
			images : {},
			loading: 'ZoomImageLoading'
		};
		Object.extend(this.options,options);
		this.element = $(container);
		this.loupe = $(this.options.loupeID);
		this.image = $(this.options.imageID);
		this.lhBox = $$("a[rel]")[0];
		this.lhBoxN= $$("span[class*=ZoomEnlarge]")[0];
		this.loupeIn = $$("a[class*=ZoomIn]")[0];
		this.loupeIn.observe('click', (function(event) {event.stop(); this.setZoomIn(event);}).bindAsEventListener(this));
		this.loupeInN= $$("span[class*=ZoomIn]")[0];
		this.loupeOut = $$("a[class*=ZoomOut]")[0];
		this.loupeOut.observe('click', (function(event) {event.stop(); this.setZoomOut(event);}).bindAsEventListener(this));
		this.loupeOutN= $$("span[class*=ZoomOut]")[0];
		this.originalStyle = {};
		this.loading = $(this.options.loading);
		this.preLoad(this.loading.firstDescendant().firstDescendant().src);
		['top','left','width','height','cursor'].each( function(k) {this.originalStyle[k] = this.image.getStyle(k); }.bind(this));
		this.originalScrollLeft = this.element.scrollLeft;
		this.originalScrollTop	= this.element.scrollTop;
		this.carousel.element.observe('carousel:imageChange', (function(event) { event.stop(); this.resetZoom(); }).bindAsEventListener(this));
		this.resetZoom();
		this.updateLoupe();
		for (i in this.options.images)
		{
			this.preLoad(this.options.images[i].preview);
		}
		for (i in this.options.images)
		{
			this.preLoad(this.options.images[i].detail);
			this.preLoad(this.options.images[i].zoom);
		}
	},

	mouseZoom: function(event)
	{
		if (event.element().tagName!='IMG') return false;
//		if (!this.isImageCompleteLoad(this.image.src)) return false;
		switch(event.type)
		{
			case 'mousedown':
				this.isDrag = true;
				this.dragX = event.pointerX();
				this.dragY = event.pointerY();
				event.stop();
				break;
			case 'mouseup':
			case 'mouseout':
				this.isDrag = false;
				this.dragX = 0;
				this.dragY = 0;
				event.stop();
				break;
			case 'mousemove':
				if (!this.isDrag) break;
				if (Math.abs(this.dragX - event.pointerX()) < 10 && Math.abs(this.dragY - event.pointerY()) < 10) break;
				var dim = this.image.getDimensions();
				this.element.scrollLeft-= event.pointerX() - this.dragX;
				this.element.scrollTop -= event.pointerY() - this.dragY;
				this.dragX= event.pointerX();
				this.dragY= event.pointerY();
				break;
		}
		return false;
	},

	setImage: function(src, resetStyle)
	{		
		if (this.image.src.indexOf(src) != -1) return;
		if (resetStyle)
		{
			this.image.setStyle(this.originalStyle);
			this.element.scrollLeft = this.originalScrollLeft;
			this.element.scrollTop	= this.originalScrollTop;
		}
		var img = new Image();
		img.src = src;
		if (img.complete)
		{
			this.onLoadImage();
		} else
		{
			this.loading.show();
			this.image.hide();
			img.onload = this.onLoadImage.bind(this);
			img.onabort= this.onLoadImage.bind(this);
			img.onerror= this.onLoadImage.bind(this);
		}
		this.image.src = src;
		if (this.lhBox) this.lhBox.href = this.getCurrentZoom();
		this.updateLoupe();
	},

	isImageCompleteLoad: function(src)
	{
		for (img in document.images)
		{
			if (document.images[img].src && document.images[img].src.indexOf(src)!=-1) return document.images[img].complete;
		}
		return false;
	},

	onLoadImage: function()
	{
		this.loading.hide();
		this.image.show();
	},

	preLoad: function(src)
	{
		(new Image()).src = src;
	},

	startZoom: function()
	{
		var src = this.getCurrentZoom();
		this.setImage(src,true);
		if (!this.isImageCompleteLoad(src))
		{
			return window.setTimeout(function() {return this.startZoom();}, 1000);
		}
		this.onLoadImage();
		this.currentZoom = 1;
		this.isDrag = false;
		this.element.observe('mousedown', (function(event) { event.stop(); this.mouseZoom(event); }).bindAsEventListener(this));
		this.element.observe('mouseup', (function(event) { event.stop(); this.mouseZoom(event); }).bindAsEventListener(this));
		this.element.observe('mousemove', (function(event) { event.stop(); this.mouseZoom(event); }).bindAsEventListener(this));
		this.element.observe('mouseout', (function(event) { event.stop(); this.mouseZoom(event); }).bindAsEventListener(this));
		this.image.setStyle({cursor:'move'});
	},

	resetZoom: function()
	{
		this.currentZoom = 0;
		this.isDrag = false;
		this.setImage(this.getCurrentDetail(),true);
		this.element.stopObserving('mousedown', this.mouseZoom);
		this.element.stopObserving('mouseup', this.mouseZoom);
		this.element.stopObserving('mousemove', this.mouseZoom);
		this.element.stopObserving('mouseout', this.mouseZoom);
	},

	setZoom: function(step)
	{
		new Effect.Scale(this.image,100+step);
		this.updateLoupe();
	},

	setZoomIn: function(event)
	{
		if (this.currentZoom == 0)
		{
			this.startZoom();
		} else
		{
			this.currentZoom += 1;
		}
		this.setZoom(25);
		return false;
	},

	setZoomOut: function()
	{
		this.currentZoom -= 1;
		if (this.currentZoom <= 1)
		{
			this.resetZoom();
		} else
		{
			this.setZoom(-20);
		}
	},

	updateLoupe: function(reset)
	{
		try
		{
			if (this.isZoomIn())
			{
				this.loupeIn.show();
				this.loupeInN.hide();
			} else
			{
				this.loupeIn.hide();
				this.loupeInN.show();
			}
			if (this.isZoomOut())
			{
				this.loupeOut.show();
				this.loupeOutN.hide();
			} else
			{
				this.loupeOutN.show();
				this.loupeOut.hide();
			}
			if (this.isZoom())
			{
				this.lhBox.show();
				this.lhBoxN.hide();
			} else
			{
				this.lhBox.hide();
				this.lhBoxN.show();
			}
		} catch(e) {}
	},

	getCurrentID: function() {return this.carousel.getCurrent().identify().replace(this.options.prefix,'');},
	getCurrentDetail: function() {return this.options.images[this.getCurrentID()].detail;},
	getCurrentZoom: function() {return this.options.images[this.getCurrentID()].zoom;},
	isZoom: function() {return this.options.images[this.getCurrentID()].zoom!='#';},
	isZoomIn: function() {return this.isZoom() && this.currentZoom < 5;},
	isZoomOut: function() {return this.isZoom() && this.currentZoom > 0;},
	_changeImage: function() {this.setCurrentID(this.carousel.getCurrent().identify());}
}

var UICarousel = Class.create();
UICarousel.prototype = {
	initialize: function(container,options)
	{
		this.options = {
			animate:true,
			limit:0,
			count:0,
			preloadClass:'Preload',
			currentClass:'Current',
			prevButton: 'ImgScrollUpArrow',
			nextButton: 'ImgScrollDownArrow'
		};
		this.element = $(container);
		this.element.childElements().each(function(elem)
		{
			if (elem.visible()) this.options.limit +=1;
			this.options.count += 1;
		}.bind(this));
		Object.extend(this.options,options);
		if (this.options.count != this.options.limit)
		{
			$(this.options.prevButton).observe('click', (function(event) { event.stop(); this.step(-1); }).bindAsEventListener(this));
			$(this.options.nextButton).observe('click', (function(event) { event.stop(); this.step(1); }).bindAsEventListener(this));
		}
		this.element.observe('click', (function(event) { event.stop(); this.changeImage(event); }).bindAsEventListener(this));
	},

	changeImage: function(event)
	{
		var el = event.element().parentNode;
		if (el.className==this.options.currentClass) return false;
		this.element.childElements().each(function(elem)
		{
			elem.className = el.identify() == elem.identify()? this.options.currentClass : this.options.preloadClass;
		}.bind(this));
		this.fire('imageChange', { });
	},

	getCurrent: function()
	{
		return this.element.getElementsByClassName(this.options.currentClass)[0];
	},

	step: function(s)
	{
		if (!s) return;
		if (this.options.animate)
			this.element.morph("opacity:0.5", {duration: 0.2, afterFinish: function(s) {this._step(s);}.bind(this)});
		else
			this._step(s);
	},

	_step: function(event,s)
	{
		var childs = this.element.childElements();
		if (s > 0)
		{
			this.element.insertBefore(childs.first(),childs.last().nextSibling);
		} else
		{
			this.element.insertBefore(childs.last(),childs.first());
		}
		var count = this.options.limit;
		this.element.childElements().each(function(elem)
		{
			if (count)
			{
				elem.show();
				count -= 1;
			} else elem.hide();
		}.bind(this));
		if (this.options.animate) this.element.morph("opacity:1", {duration: 0.2});
	},

	fire: function(eventName, memo)
	{
		memo = memo || { };
		memo.carousel = this;
		return this.element.fire('carousel:' + eventName, memo);
	}
}
