/*--------------------------------------------------------------------------*
 * 
 * Category Zoom (Whitney)
 * 
 * Version 3.0.0
 * 
 * Copyright (C) 2009 Brand Labs LLC
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
 * 02110-1301  USA
 * 
 *--------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------*
 * Main Module
 *--------------------------------------------------------------------------*/
var Whitney = {
	load: function() {
		try {
			//CATEGORY
			//Only load on the category page (per Volusion KB)
			if (location.pathname.toLowerCase() == '/searchresults.asp' ||
			location.pathname.toLowerCase().indexOf('-s/') != -1 ||
			location.pathname.toLowerCase().indexOf('_s/') != -1) {
				//CATEGORY ZOOM
				if (WhitneyCategoryZoomSettings.ENABLED) {
					WhitneyCategoryZoomStartup.load();
				}
			}
		}
		catch(e) {/*No-op*/}
	}
};
/*--------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------*
 * Start up the module
 *--------------------------------------------------------------------------*/
Event.observe(window, 'load', Whitney.load);
/*--------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------*
 * ZOOM
 *--------------------------------------------------------------------------*/
var WhitneyZoom = Class.create({
	initialize: function() {
		//Settings
		this.productCode = null;
		this.photosPath = null;
		this.mainPhotoElement = null;
		this.mainPhotoAnchorElement = null;		
		this.noPhotoFileName = null;
		this.overlayOpacity = null;
		this.allowClickOnViewPort = null;
		this.displayZoomOnRight = null;
		this.displayZoomOnTop = null;
		this.getPhotosURLTemplate = null;
		
		//Instance variables
		this.body = null;
		this.mainPhotoWidth = null;
		this.mainPhotoHeight = null;
		this.mainPhotoLeft = null;
		this.mainPhotoTop = null;		
		this.mainPhotoBorderLeft = null;
		this.mainPhotoBorderTop = null;
		this.mainPhotoBorderRight = null;
		this.mainPhotoBorderBottom = null;				
		this.overlayElement = null;
		this.viewPortElement = null;
		this.viewPortElementImage = null;
		this.zoomedPhotoElement = null;
		this.zoomedPhotoElementImage = null;
		this.moveEventListener = null;
		this.photoData = null;
		this.zoomRatio = null;
		
		this.currentX = null;
		this.currentY = null;
	},
	
	load: function() {
		var mainFileName;
				
		try {
			//Get the body
			this.body = $$('body').first();
		}
		catch(e) {return;/*Ignore*/}
		
		//Skip, missing body element
		if(this.mainPhotoElement == null || this.body == null) {
			return;
		}

		//Check for "No Photo" condition
		mainFileName = this.mainPhotoElement.src;
		if(mainFileName == null || mainFileName.indexOf(this.noPhotoFileName) != -1) {
			return;
		}

		//Setup observation				
		Event.observe(this.mainPhotoElement, 'mouseover', this.entered.bindAsEventListener(this));
	},
	
	move: function(event) {
		this.currentX = Event.pointerX(event);
		this.currentY = Event.pointerY(event);
		this.moveItems();
	},
	
	moveItems: function() {
		var x = this.currentX;
		var y = this.currentY;
		
		//Check for missing photo
		if(this.mainPhotoElement == null) {
			return;
		}
						
		/*Check Bounds*/
		//Left bounds
		if(x < (this.mainPhotoLeft-this.mainPhotoBorderLeft)) {
			this.exited();
			return;	
		}
		//Right bounds
		if(x > (this.mainPhotoLeft+this.mainPhotoWidth+this.mainPhotoBorderRight) ) {
			this.exited();
			return;	
		}
		//Top bounds
		if(y < (this.mainPhotoTop-this.mainPhotoBorderTop)) {
			this.exited();
			return;	
		}
		//Bottom bounds
		if(y > (this.mainPhotoTop+this.mainPhotoHeight+this.mainPhotoBorderBottom) ) {
			this.exited();
			return;	
		}				
		/*End Check Bounds*/
		
		
		//Move the view port
		this.moveViewPort();
		//Move the zoomed location
		this.moveZoomedPhoto();
	},			
	
	moveViewPort: function() {
		var viewPortElement = this.viewPortElement;
		var viewPortElementImage = this.viewPortElementImage;
		var width;
		var height;
		var halfWidth;
		var halfHeight;
		var adjustedX;
		var adjustedY;
		
		var x = this.currentX;
		var y = this.currentY;
		
		//Skip if missing element
		if(viewPortElement == null || viewPortElementImage == null) {
			return;
		}

		width = viewPortElement.getWidth();
		height = viewPortElement.getHeight();
		halfWidth = width / 2;
		halfHeight = height / 2;
		
		adjustedX = x;
		adjustedY = y;
						
		/*Bounds Checks*/	 
		//Left bounds
		if(this.mainPhotoLeft > (x-halfWidth)) {
			adjustedX = this.mainPhotoLeft + halfWidth;
		}								
		//Right bounds
		if( (this.mainPhotoLeft+this.mainPhotoWidth) < (x+halfWidth) ) {
			adjustedX = this.mainPhotoLeft + this.mainPhotoWidth - halfWidth;
		}
		//Top bounds
		if(this.mainPhotoTop > (y-halfHeight)) {
			adjustedY = this.mainPhotoTop + halfHeight;
		}
		//Bottom bounds
		if( (this.mainPhotoTop+this.mainPhotoHeight) < (y+halfHeight) ) {
			adjustedY = this.mainPhotoTop + this.mainPhotoHeight - halfHeight;
		}
		/*End Bounds Checks*/					
		
		viewPortElement.setStyle({
			left: adjustedX - halfWidth
				+ 'px',
			top: adjustedY - halfHeight
				+ 'px'
		});	

		/*viewPortElementImage.setStyle({
			marginLeft: -(adjustedX - this.mainPhotoLeft) + (halfWidth+this.mainPhotoBorderLeft-1)
				+ 'px',
			marginTop:  -(adjustedY - this.mainPhotoTop) + (halfHeight+this.mainPhotoBorderTop-1)
				+ 'px'
		});*/
		viewPortElementImage.setStyle({
			marginLeft: -(adjustedX - this.mainPhotoLeft) + (halfWidth-1)
				+ 'px',
			marginTop:  -(adjustedY - this.mainPhotoTop) + (halfHeight-1)
				+ 'px'
		});
	},
	
	moveZoomedPhoto: function() {
		var zoomedPhotoElement = this.zoomedPhotoElement;
		var zoomedPhotoElementImage = this.zoomedPhotoElementImage;
		var width;
		var height;
		var largeWidth;
		var largeHeight;
		var halfWidth;
		var halfHeight;
		
		var x = this.currentX;
		var y = this.currentY;
		
		//Skip if missing element
		if(zoomedPhotoElement == null || zoomedPhotoElementImage == null) {
			return;
		}
		
		width = zoomedPhotoElement.getWidth();
		height = zoomedPhotoElement.getHeight();
		halfWidth = width / 2;
		halfHeight = height / 2;
		
		largeWidth = this.mainPhotoWidth * this.zoomRatio;
		largeHeight = this.mainPhotoHeight * this.zoomRatio;
		
		var marginLeft = -( (x-this.mainPhotoLeft) * this.zoomRatio) + halfWidth;
		var marginTop = -( (y-this.mainPhotoTop) * this.zoomRatio) + halfHeight;

		/*Find limits*/
		if(marginLeft > 0) {
			marginLeft = 0;
		}
		else if(marginLeft < (width-largeWidth) ) {
			marginLeft = width - largeWidth;
		}				
		
		if(marginTop > 0) {
			marginTop = 0;
		}
		else if(marginTop < (height-largeHeight) ) {
			marginTop = height - largeHeight;
		}
		/* */

		//Move image (well change margin)
		zoomedPhotoElementImage.setStyle({
			marginLeft: marginLeft + 'px',
			marginTop: marginTop + 'px'
		});			
	},
	
	entered: function(event) {
		var thisObj = this;
		var url = null;
		var x = Event.pointerX(event);
		var y = Event.pointerY(event);
		var mainPhotoPosition = null;
		var imageElement = null;

		this.currentX = x;
		this.currentY = y;
		
		//Make sure there is a photo element
		if(this.mainPhotoElement == null) {
			return;
		}
		
		//Opps, already listening
		if(this.moveEventListener != null) {
			return;
		}

		//Get information about image size
		mainPhotoPosition = this.mainPhotoElement.positionedOffset();
		this.mainPhotoLeft = mainPhotoPosition.left;
		this.mainPhotoTop = mainPhotoPosition.top;
		this.mainPhotoWidth = this.mainPhotoElement.getWidth();
		this.mainPhotoHeight = this.mainPhotoElement.getHeight();
		
		//Caclulate photo border			
		this.mainPhotoBorderLeft = this.parseWidth(this.mainPhotoElement.getStyle('borderLeftWidth'));
		this.mainPhotoBorderTop = this.parseWidth(this.mainPhotoElement.getStyle('borderTopWidth'));
		this.mainPhotoBorderRight = this.parseWidth(this.mainPhotoElement.getStyle('borderRightWidth'));
		this.mainPhotoBorderBottom = this.parseWidth(this.mainPhotoElement.getStyle('borderBottomWidth'));

		//Change photo width/height/top/left
		this.mainPhotoWidth = this.mainPhotoWidth - this.mainPhotoBorderLeft - this.mainPhotoBorderRight;
		this.mainPhotoHeight = this.mainPhotoHeight - this.mainPhotoBorderTop - this.mainPhotoBorderBottom;
		this.mainPhotoLeft = this.mainPhotoLeft + this.mainPhotoBorderLeft;
		this.mainPhotoTop = this.mainPhotoTop + this.mainPhotoBorderTop;
					
		//Observe for the entire window!		
		this.moveEventListener = this.move.bindAsEventListener(this);
		Event.observe(this.body, 'mousemove', this.moveEventListener);							
		
		//Check for existing data first
		if(this.photoData != null) {
			this.enteredCallback();
			return;
		}
		
		//Create URL
		url = this.photosPath 
			+ '/' 
			+ this.productCode
			+ '-'
			+ this.getCurrentFileNumber()
			+ this.mainPhotoElement.src.substring(this.mainPhotoElement.src.lastIndexOf('.')) /*file extension*/;
		
		//Load the image
		imageElement = new Element('img', {});
		
		//Show the waiting
		this.startShowingWait();
		
		//Loading successful
		Event.observe(imageElement, 'load', function() {			
			//Remove events
			Event.stopObserving(imageElement);
			
			//Stop the wait mode
			thisObj.stopShowingWait();					
			
			//Make sure something is back
			if(imageElement.width == null || imageElement.height == null) {
				return;
			}
			if(imageElement.width <= 0 || imageElement.height <= 0) {
				return;
			}
			
			//Store image data
			thisObj.photoData = {
				fileName: imageElement.src,
				width: imageElement.width,
				height: imageElement.height
			};
			
			//Continue and create popup
			thisObj.enteredCallback();			
		});
		//Loading error
		Event.observe(imageElement, 'error', function() {
			//Remove events
			Event.stopObserving(imageElement);
			
			thisObj.stopShowingWait();
			thisObj.exited();
		});
		
		//Set URL to load image
		imageElement.src = url;
	},
		
	enteredCallback: function() {
		var x = this.currentX;
		var y = this.currentY;

		//Check for empty			
		if(this.photoData == null) {
			return;
		}		
		
		//Do not show, same size
		if(this.mainPhotoWidth >= this.photoData.width 
			&& this.mainPhotoHeight >= this.photoData.height) {
			this.exited();
			return;
		}
				
		//Calculate the zoom ratio
		this.zoomRatio = this.photoData.width / this.mainPhotoWidth;
		
		//Create elements
		this.createOverlay();
		this.createViewPort();
		this.createZoomedPhoto();
		
		//Click of view port will bring up same URL
		if (this.allowClickOnViewPort) {
			Event.observe(this.viewPortElement, 'click', this.viewPortClicked.bindAsEventListener(this));
		}			
		
		//Make sure to move
		this.moveItems();	
	},
	
	/**
	 * Parses a CSS width to remove the 'px' from it
	 * 
	 * @param {Object} cssWidth
	 */
	parseWidth: function(cssWidth) {
		var location;
		
		if(cssWidth == null) {
			return 0;
		}
		
		location = cssWidth.indexOf('px');
		
		if(location == -1) {
			return 0;
		}
		
		return Number(cssWidth.substring(0, location));
	},
	
	viewPortClicked: function() {
		var mainPhotoAnchor = this.mainPhotoAnchorElement;
			
		if(mainPhotoAnchor == null) {
			return;
		}
		
		window.location.href = mainPhotoAnchor.href;		
	},
	
	exited: function() {
		//Remove the elements we added
		this.removeZoomedPhoto();
		this.removeViewPort();
		this.removeOverlay();
		
		//Stop the observation
		if (this.moveEventListener != null) {
			Event.stopObserving(this.body, 'mousemove', this.moveEventListener);
			this.moveEventListener = null;
		}
	},
	
	createOverlay: function() {
		var overlayElement = null;
		
		//Check for pre-existing, if so, do not create
		if(this.overlayElement != null) {
			return;
		}
		
		//Create the "div"
		overlayElement = new Element('div', {
			style: 'display: none;'
		});
		overlayElement.addClassName('whitney_overlay_class');
		this.overlayElement = overlayElement;
		
		overlayElement.setStyle({
			position: 'absolute', 					
			width: this.mainPhotoWidth + 'px',
			height: this.mainPhotoHeight + 'px',
			left: this.mainPhotoLeft + 'px',
			top: this.mainPhotoTop + 'px',
			overflow: 'hidden',
			zIndex: 100,
			opacity: this.overlayOpacity
		});
		
		//Add and display
		this.body.insert(overlayElement);
		overlayElement.show();
	},
	
	removeOverlay: function() {
		//Make sure we have something
		if(this.overlayElement == null) {
			return;
		}
		
		//Remove the element
		this.overlayElement.hide();
		this.overlayElement.remove();
		this.overlayElement = null;
	},
	
	createViewPort: function() {
		var viewPortElement = null;
		var viewPortElementImage = null;
		var width;
		var height;
		
		var x = this.currentX;
		var y = this.currentY;		
		
		//Check for pre-existing, if so, skip
		if(this.viewPortElement != null) {
			return;
		}				
		
		//Calculate size
		width = this.mainPhotoWidth / this.zoomRatio;
		height = this.mainPhotoHeight / this.zoomRatio;
		
		//Create elements
		viewPortElement = new Element('div', {
			style: 'display: none;'
		});
		this.viewPortElement = viewPortElement;
		viewPortElementImage = new Element('img', {			
			src: this.mainPhotoElement.src,
			alt: this.mainPhotoElement.alt,
			title: this.mainPhotoElement.title,
			width: this.mainPhotoWidth + 'px',
			height: this.mainPhotoHeight + 'px'
		});
		viewPortElementImage.setStyle({
			width: this.mainPhotoWidth + 'px',
			height: this.mainPhotoHeight + 'px'
		});
		this.viewPortElementImage = viewPortElementImage;
		
		viewPortElement.addClassName('whitney_view_port_class');
		viewPortElement.setStyle({
			position: 'absolute',
			width: width + 'px',
			height: height + 'px',
			
			overflow: 'hidden',
			zIndex: 101,
			backgroundColor: 'transparent'
		});
		viewPortElementImage.addClassName('whitney_view_port_image_class');
		viewPortElement.update(viewPortElementImage);
		
		//Add
		this.body.insert(viewPortElement);
		//Move it to the proper location
		this.moveViewPort();
		//Display
		viewPortElement.show();			
	},
	
	removeViewPort: function() {
		//Make sure we have something
		if(this.viewPortElement == null) {
			return;
		}
		
		//Remove the element
		this.viewPortElement.hide();
		this.viewPortElement.remove();
		this.viewPortElement = null;
		this.viewPortElementImage = null;
	},
				
	createZoomedPhoto: function() {
		var zoomedPhotoElement = null;
		var zoomedPhotoElementImage = null;
		var zoomedPhotoIFrame = null;
		var left;
		var top;

		var x = this.currentX;
		var y = this.currentY;
		
		//Check for pre-existing, if so, exit
		if(this.zoomedPhotoElement != null) {
			return;
		}
		
		/*Zoomed Photo Location*/
		//Display to the right
		if(this.displayZoomOnRight) {
			left = this.mainPhotoLeft + this.mainPhotoWidth;
		}
		//Display to the left
		else {
			left = this.mainPhotoLeft - this.mainPhotoWidth;
		}
		//Display on the top
		if(this.displayZoomOnTop) {
			top = this.mainPhotoTop -1/*Border (just top)*/;
		}
		//Display on the bottom
		else {
			top = this.mainPhotoTop + this.mainPhotoHeight;	
		}
		/* */
		
		//Create elements
		zoomedPhotoElement = new Element('div', {			
			style: 'display: none;'
		});
		this.zoomedPhotoElement = zoomedPhotoElement;
		zoomedPhotoElement.addClassName('whitney_zoomed_photo_class');

		zoomedPhotoElementImage = new Element('img', {			
			src: this.photoData.fileName,
			alt: this.mainPhotoElement.alt,
			title: this.mainPhotoElement.title,
			width: this.photoData.width + 'px',
			height: this.photoData.height + 'px',
			border: '0'
		});
		zoomedPhotoElementImage.addClassName('whitney_zoomed_photo_image_class');
		zoomedPhotoElementImage.setStyle({
			width: this.photoData.width + 'px',
			height: this.photoData.height + 'px'				
		});
		this.zoomedPhotoElementImage = zoomedPhotoElementImage;
							
		//Style elements
		zoomedPhotoElement.setStyle({
			position: 'absolute', 			
			width: this.mainPhotoWidth + 'px',
			height: this.mainPhotoHeight + 'px',			
			top: top + 'px',
			left: left + 'px',			
			overflow: 'hidden',
			zIndex: 102
		});			
		zoomedPhotoElement.update(zoomedPhotoElementImage);	
		
		//Add to body and display (with effects)
		this.body.insert(zoomedPhotoElement);
		//Move it to the proper location
		this.moveZoomedPhoto();
		//Display		
		zoomedPhotoElement.show();
	},
	
	removeZoomedPhoto: function() {
		//Make sure we have something
		if(this.zoomedPhotoElement == null) {
			return;
		}
		
		//Remove the element
		this.zoomedPhotoElement.hide();
		this.zoomedPhotoElement.remove();
		this.zoomedPhotoElement = null;
		this.zoomedPhotoElementImage = null;		
	},
	
	/**
	 * Outsourced, the function must be implemented by non-abstract implementation
	 */
	getCurrentFileNumber: function() {
	},
	
	/**
	 * 
	 */
	startShowingWait: function() {
		if (this.mainPhotoElement != null) {
			this.mainPhotoElement.setStyle({
				cursor: 'wait'
			});
		}
		if (this.mainPhotoAnchorElement != null) {
			this.mainPhotoAnchorElement.setStyle({
				cursor: 'wait'
			});
		}
	},
	
	/**
	 * 
	 */
	stopShowingWait: function() {
		if (this.mainPhotoElement != null) {
			this.mainPhotoElement.setStyle({
				cursor: 'auto'
			});
		}
		if (this.mainPhotoAnchorElement != null) {
			this.mainPhotoAnchorElement.setStyle({
				cursor: 'auto'
			});
		}
	}	
});
/*--------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------*
 * CATEGORY
 *--------------------------------------------------------------------------*/
var WhitneyCategoryZoomSettings = {
	ENABLED: false,
	
	VIEW_PORT_WIDTH: 140,
	VIEW_PORT_HEIGHT: 140,
	NO_PHOTO_FILE_NAME: 'nophoto.gif',
	OVERLAY_OPACITY: 0.5,
	ALLOW_CLICK_ON_VIEW_PORT: true,
	DISPLAY_ZOOM_ON_RIGHT: true,
	DISPLAY_ZOOM_ON_TOP: true,
	
	PHOTOS_PATH: '/v/vspfiles/photos',
	MORE_INFO_FILE_NAME: 'Bullet_MoreInfo.gif',
	ADD_TO_CART_FILE_NAME: 'btn_addtocart_small.gif',
	NO_PHOTO_FILE_NAME: 'nophoto.gif',	
	CONTENT_AREA_ID: 'content_area'
};

var WhitneyCategoryZoom = Class.create(WhitneyZoom, {
	initialize: function($super) {
		$super();
	},
	
	/**
	 * Only the first file, not any others
	 */
	getCurrentFileNumber: function() {
		return 2;
	}	
});

var WhitneyCategoryZoomStartup = {
	/**
	 * 
	 */
	load: function() {
		var contentAreaElement = null;
		var anchors = null;
		
		//See if we get the elements
		try {
			contentAreaElement = $(WhitneyCategoryZoomSettings.CONTENT_AREA_ID);
			
			//Check for missing element
			if(contentAreaElement == null) {
				return;
			}
			
			anchors = contentAreaElement.select('a');
			
			//Make sure there are anchors
			if(anchors == null || anchors.size < 1) {
				return null;
			}
		
			anchors.each(function(item) {
				var images = null;
				var image = null;
				var productCode = null;
				var zoom = null;
				
				//Get the product code from the URL, else skip
				productCode = WhitneyCategoryZoomStartup.getProductCodeFromURL(item.href);			
				if(productCode == null) {
					return;
				}
				
				//Get all the images
				images = item.select('img');
				
				//Must have one image, skip if not
				if(images == null || images.size() != 1) {
					return;
				}
				image = images.first();
				
				//Special image to skip!
				if(image.src.toLowerCase().indexOf(WhitneyCategoryZoomSettings.MORE_INFO_FILE_NAME.toLowerCase()) != -1) {
					return;
				}
				if(image.src.toLowerCase().indexOf(WhitneyCategoryZoomSettings.ADD_TO_CART_FILE_NAME.toLowerCase()) != -1) {
					return;
				}
				if(image.src.toLowerCase().indexOf(WhitneyCategoryZoomSettings.NO_PHOTO_FILE_NAME.toLowerCase()) != -1) {
					return;
				}				
				
				//Create the zoom for that image	
				zoom = new WhitneyCategoryZoom();
	
				zoom.noPhotoFileName = WhitneyCategoryZoomSettings.NO_PHOTO_FILE_NAME;
				zoom.overlayOpacity = WhitneyCategoryZoomSettings.OVERLAY_OPACITY;
				zoom.allowClickOnViewPort = WhitneyCategoryZoomSettings.ALLOW_CLICK_ON_VIEW_PORT;
				zoom.displayZoomOnRight = WhitneyCategoryZoomSettings.DISPLAY_ZOOM_ON_RIGHT;
				zoom.displayZoomOnTop = WhitneyCategoryZoomSettings.DISPLAY_ZOOM_ON_TOP;
				zoom.getPhotosURLTemplate = WhitneyCategoryZoomSettings.GET_PHOTOS_URL_TEMPLATE;
				
				zoom.productCode = productCode;
				zoom.photosPath = WhitneyCategoryZoomSettings.PHOTOS_PATH;
				zoom.mainPhotoElement = image;
				zoom.mainPhotoAnchorElement = item;
	
				zoom.load();			
			});	
		}
		catch(e) {
			return;
		}	
	},
	
	/**
	 * 
	 * @param {Object} url
	 */
	getProductCodeFromURL: function(url) {
		var matches = null;
		
		//Make sure we do not have a null
		if(url == null) {
			return null;
		}
		
		//Check non-SEO URL
		matches = url.match(/\/productdetails\.asp\?(?:[\&]?.*\=.*)*productcode=([^\&\#]+)/i);	
		if(matches != null && matches.length >= 2) {
			return unescape(matches[1]);
		}
		
		//Check SEO URL
		matches = url.match(/(?:_p|-p)\/(.+)\.htm/i);	
		if(matches != null && matches.length >= 2) {
			return unescape(matches[1]);
		}
	
		//No product code available
		return null;
	}	
};
/*--------------------------------------------------------------------------*/
