var ImageZoom = new Class({

	Implements: [Options],
	Images: [],
	options: {
		"selector": "a[rel=ImageZoom]",
		"classes": {
			placeholder  : "ImageZoom",
			looking_glass:"ImageZoomGlass",
			magnified: "ImageZoomMagnified"
		},
		"cancel_click" : true,
		"magnified_pos": "fixed"
	},
	overlay: null, 

	initialize:  function(options) { 
		this.setOptions(options);		
		this.Images = $$( this.options.selector + " img" );
		var that = this;
		
		this.Images.each(function(elm, i){
			
			var elmSize = $(elm).getSize();
			var parent_a = elm.getParent("a");
			var lg_href = parent_a.get("href");
			
			parent_a.setStyles({
				"position":		"relative", 
				"display": 		"block", 
				"z-index": 		50, 
				"width": 		elmSize.x, 
				"height": 		elmSize.y
				});
			
			var rel_pos = parent_a.getPosition( elm );
			
			if( that.options.cancel_click ) {
				parent_a.addEvent("click", function(e){
					e.preventDefault();
				});
			}
			
			var lgimg = that.image( lg_href, { "onload" : function(){
				
				var repImg = new Element("div", {"class":that.options.classes.placeholder, "styles":{ 
						"background": 	"url(" + escape(elm.getProperty("src")) + ")",
						"position":		"absolute", 
						"z-index": 		50, 
						"width" : 		elmSize.x, 
						"height": 		elmSize.y, 
						"top"   : 		rel_pos.x,
						"left"  : 		rel_pos.y
				}});						

				repImg.inject( parent_a );

				var zomml = new Element("div", {"class":that.options.classes.looking_glass} ).inject( repImg );
				zommlSize = zomml.getSize();
				zomml.fade("hide");

				var zommm = new Element("div", {"class":that.options.classes.magnified, "styles":{ 
						"background": "url(" + escape(lg_href) + ")",
						"width"     : zommlSize.x / elmSize.x * lgimg.width,
						"height"    : zommlSize.y / elmSize.y * lgimg.height
				}});
				
				if( that.options.magnified_pos == "fixed" ) {
					zommm.inject( repImg );
				}else{
					zommm.inject( zomml );
				}
				
				$(elm).setStyle("visibility", "hidden");
				
				var zommmSize  = zommm.getSize(),
					zommlSize  = zomml.getSize(),
					repImgPos = repImg.getPosition();

				repImg.addEvent("mouseover", function(){

					var windowSize = window.getSize();
					repImgPos = repImg.getPosition();
					if( Math.abs(elmSize.x - ( windowSize.x - repImgPos.x )) > zommlSize.x ){
					}else{
						if( that.options.magnified_pos == "fixed" ) {
							zommm.setStyle("left",  0 - zommmSize.x );
						}else{
							zommm.setStyle("right", zommmSize.x );
						}
					}
					var bdy = $(document).getElement("body");
					var crd = bdy.getScrollSize();
					
					if(this.overlay){
						this.overlay.destroy();
						}
					
					this.overlay = new Element("div", {"class": "ImageZoomOverlay", "styles": {"z-index": 10, "width": crd.x, "height": crd.y}});
					this.overlay.inject(bdy);
					
					zomml.fade("in");
					if( that.options.magnified_pos == "fixed" ) zommm.fade("in");
				});

				repImg.addEvent("mouseout", function(){
					if(this.overlay){
						this.overlay.destroy();
						}
						
					zomml.fade("out");
					if( that.options.magnified_pos == "fixed" ) zommm.fade("out");
				});
				
				repImg.fireEvent("mouseout");

				repImg.addEvent("mousemove", function(ev){
					var posY = (ev.page.y - zommlSize.y / 2) - repImgPos.y;
					var posX = (ev.page.x - zommlSize.x / 2) - repImgPos.x;
					zomml.setStyle("top", posY.limit(0, elmSize.y - zommlSize.y ) );
					zomml.setStyle("left", posX.limit(0, elmSize.x - zommlSize.x ) );
					zommm.setStyle("background-position", ((posX / (elmSize.x - zommlSize.x)) * 100).limit(0,100) + "% " + ((posY / (elmSize.y - zommlSize.y)) * 100).limit(0,100) + "%" );

				});

				//Internet Explorer Garbage
				if( Browser.Engine.trident ) {
					repImg.setStyles({ "background":"url("+escape(elm.get("src"))+")" });
					repImg.addEvent("mouseover", function(){ $$("select").fade("out");});
					repImg.addEvent("mouseout",  function(){ $$("select").fade("in"); });
				}

			}});

		});
	},
	

	image: function(source, properties){
		properties = $merge({
			onload: $empty,
			onabort: $empty,
			onerror: $empty
		}, properties);
		var image = new Image();
		var element = document.id(image) || new Element("img");
		["load", "abort", "error"].each(function(name){
			var type = "on" + name;
			var cap = name.capitalize();
			if (properties["on" + cap]) properties[type] = properties["on" + cap];
			var event = properties[type];
			delete properties[type];
			image[type] = function(){
				if (!image) return;
				if (!element.parentNode){
					element.width = image.width;
					element.height = image.height;
				}
				image = image.onload = image.onabort = image.onerror = null;
				event.delay(1, element, element);
				element.fireEvent(name, element, 1);
			};
		});
		image.src = element.src = source;
		if (image && image.complete) image.onload.delay(1);
		return element.set(properties);
	}
	
});
