var ProductZoomer = new Class({
	
	initialize: function(
			zoomPicture,
			zoomBox,
			zoomBoxImage,
			zoomPictureScaled, 
			zoomPictureScaledBox,
			origWidth,
			origHeight,
			zoomImageHeight,
			anchorZoomOriginal,
			anchorZoomIn,
			anchorZoomOut) {
		
		// set the boxes
		this.zoomPicture = zoomPicture;
		this.zoomBox = zoomBox;
		this.zoomBoxImage = zoomBoxImage;
		this.zoomPictureScaled = zoomPictureScaled;
		this.zoomPictureScaledBox = zoomPictureScaledBox;
		
		// set dimensions
		this.origWidth = origWidth;
		this.origHeight = origHeight;
		this.scaledWidth = zoomPictureScaled.getStyle('width').toInt();
		this.zoomImageHeight = zoomImageHeight.toInt();
		this.zoomImageWidth = this.zoomPicture.getStyle('width').toInt();
		this.zoomPictureInitialHeight = 0;
		this.zoomPictureInitialWidth = 0;
		
		// anchors
		anchorZoomOriginal.addEvent('click', this.zoomToOriginalSize.bind(this));
		anchorZoomIn.addEvent('click', this.zoomIn.bind(this));
		anchorZoomOut.addEvent('click', this.zoomOut.bind(this));
		
		// add dragging for selector
		new Drag.Move('zoomBox', {'container': zoomPictureScaledBox});
		zoomBox.addEvent('mousedown', this.dragStart.bind(this));
		zoomBox.addEvent('mouseup', this.dragStop.bind(this));
		zoomPictureScaledBox.addEvent('mousemove', this.moveImage.bind(this));
				
		// zoom values
		this.zoom = 100;
		this.semaphoreBlock = 0;
		
		// initialization for first time
		this.setScaledHeights();
		this.resizeZoomBox(this.zoom);
	},
	
	/**
	 * Moves the big image...
	 * @param {Object} e
	 */
	moveImage: function(e) {
		e = new Event(e);
		if (this.dragStarted == 1) {
			var x = e.client.x;
			var y = e.client.y;
			
			var height = this.zoomBox.getStyle('height').toInt();
			var width = this.zoomBox.getStyle('width').toInt();
			
			var left = this.zoomBox.getStyle('left').toInt() - x;
			var top = this.zoomBox.getStyle('top').toInt() - y;
			
			if (left >= 0 && left < (this.zoomPictureScaledBox.getStyle('width').toInt() - width)) {
				this.zoomBox.setStyle('left', left);
			} else if (left > (this.zoomPictureScaledBox.getStyle('width').toInt() - width)) {
				this.zoomBox.setStyle('left', (this.zoomPictureScaledBox.getStyle('width').toInt() - width));
			}
			
			if (top >= 0 && top < (this.zoomPictureScaledBox.getStyle('height').toInt() - height)) {
				this.zoomBox.setStyle('top', top);
			}
			
			// calculation depends on the first small dimension of the image -> save it
			if (this.zoomPictureInitialHeight == 0 && !isNaN(this.zoomPicture.getStyle('height').toInt())) {
				this.zoomPictureInitialHeight = this.zoomPicture.getStyle('height').toInt();
			}			
			if (this.zoomPictureInitialWidth == 0 && !isNaN(this.zoomPicture.getStyle('width').toInt())) {
				this.zoomPictureInitialWidth = this.zoomPicture.getStyle('width').toInt();
			}
			
			top = this.zoomBox.getStyle('top').toInt() * (this.zoomPictureInitialHeight / this.scaledHeight) * this.zoom / 100;
			left = this.zoomBox.getStyle('left').toInt() * (this.zoomPictureInitialWidth / this.scaledWidth) * this.zoom / 100;
			
			if (top > 0) {
				top *= -1;
			}
			if (left > 0) {
				left *= -1;
			}
			
			this.zoomPicture.setStyle('top', top);
			this.zoomPicture.setStyle('left', left);
		}
	},
	
	/**
	 * Marks that the drag was started.
	 * @param {Object} e
	 */
	dragStart: function(e) {
		this.dragStarted = 1;
	},
	
	/**
	 * Marks that the drag was stopped.
	 * @param {Object} e
	 */
	dragStop: function(e) {
		this.dragStarted = 0;
	},
	
	/**
	 * Zooms the image back to original size
	 * @param {Object} e
	 */
	zoomToOriginalSize: function(e) {
		if (this.semaphoreBlock == 1) {
			return;
		}
		this.semaphoreBlock = 1; // block other actions
		var oldZoomValue = this.zoom;
		this.zoom = 100;	
		this.zoomOutLoop(oldZoomValue);
	},
	
	/**
	 * Zooms into the image.
	 * @param {Object} e
	 */
	zoomIn: function(e) {
		if (this.semaphoreBlock == 1) {
			return;
		}
		this.semaphoreBlock = 1; // block other actions
		var oldZoomValue = this.zoom;
		this.zoom += 20;
		if (this.zoom > 200) {
			this.zoom = 200;
		}		
		this.zoomInLoop(oldZoomValue);
	},
	
	/**
	 * Zooms the image in, step by step
	 * @param {Object} zoomFactor
	 */
	zoomInLoop: function(zoomFactor) {
		if (this.zoom != zoomFactor) {
			zoomFactor++;
			this.resizeZoomBox(zoomFactor);
			this.zoomPicture.setStyle('width', zoomFactor + '%');
			// TODO make smoooooth
			this.zoomInLoop(zoomFactor);
		} else {
			this.semaphoreBlock = 0;
		}
	},
	
	/**
	 * Zooms the image out.
	 * @param {Object} e
	 */
	zoomOut: function(e) {
		if (this.semaphoreBlock == 1) {
			return;
		}
		this.semaphoreBlock = 1; // block other actions
		var oldZoomValue = this.zoom;
		this.zoom -= 20;
		if (this.zoom < 100) {
			this.zoom = 100;
		}		
		this.zoomOutLoop(oldZoomValue);
	},
	
	/**
	 * Zooms the image out, step by step.
	 * @param {Object} zoomFactor
	 */
	zoomOutLoop: function(zoomFactor) {
		if (this.zoom != zoomFactor) {
			zoomFactor--;
			this.resizeZoomBox(zoomFactor);
			this.zoomPicture.setStyle('width', zoomFactor + '%');
			// TODO make smoooooth
			this.zoomOutLoop(zoomFactor);
		} else {
			this.semaphoreBlock = 0;
		}
	},
	
	/**
	 * Scales the preview image and its box.
	 */
	setScaledHeights: function() {
		this.scaledHeight = (this.origHeight / (this.origWidth / this.scaledWidth)).toInt();
		this.zoomPictureScaled.setStyle('height', this.scaledHeight);
		this.zoomBoxImage.setStyle('height', this.scaledHeight);
		this.zoomBoxImage.setStyle('width', this.scaledHeight);
		this.zoomPictureScaledBox.setStyle('height', this.scaledHeight + 2);
	},
	
	/**
	 * Resizes the selection box.
	 * @param {Object} zoomFactor
	 */
	resizeZoomBox: function(zoomFactor) {
		var height = Math.floor((this.scaledHeight * (this.zoomImageHeight / this.zoomImageWidth)) / zoomFactor * 100);
		var width = Math.floor(this.scaledWidth / zoomFactor * 100);
		var top = this.zoomBox.getStyle('top').toInt();
		var left = this.zoomBox.getStyle('left').toInt();
		
		this.zoomBox.setStyle('width', width);
		this.zoomBox.setStyle('height', height);
		
		if ((top + height) > this.scaledHeight) {
			this.zoomBox.setStyle('top', (this.scaledHeight - height));
		}
		
		if ((left + width) > this.scaledWidth) {
			this.zoomBox.setStyle('left', this.scaledWidth - width);
		}
		
		this.adjustZoomImagePosition();
	},
	
	/**
	 * Adjusts the position of the selection box.
	 */
	adjustZoomImagePosition: function() {
		var top = Math.floor(this.zoomBox.getStyle('top').toInt() * (this.zoomImageWidth / this.scaledWidth) * this.zoom / 100);
		var left = Math.floor(this.zoomBox.getStyle('left').toInt() * (this.zoomImageWidth / this.scaledWidth) * this.zoom / 100);
		if (top > 0) {
			top *= -1;
		}
		if (left > 0) {
			left *= -1;
		}
		
		this.zoomPicture.setStyle('top', top);
		this.zoomPicture.setStyle('left', left);
	}
});