/*--------------------------------------------------------------------------*
 * 
 * Category Preview (Thames)
 * 
 * Version 1.0.8
 * 
 * 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 (at your option) 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 Thames = {
	load: function() {		
		//Decide what to load, if anything
		//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 PREVIEW
			if (ThamesCategoryPreviewSettings.ENABLED) {
				ThamesCategoryPreview.load();
			}
		}
	}
};
/*--------------------------------------------------------------------------*/


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


/*--------------------------------------------------------------------------*
 * CATEGORY PREVIEW
 *--------------------------------------------------------------------------*/
var ThamesCategoryPreviewSettings = {
	ENABLED: false,
	
	PHOTOS_PATH: '/v/vspfiles/photos',
	MORE_INFO_FILE_NAME: 'Bullet_MoreInfo.gif',
	ADD_TO_CART_URL_TEMPLATE: new Template('/ShoppingCart.asp?ProductCode=#{productCode}'),
	GET_PHOTOS_URL: '/v/thames_get_photos.asp',
	PHOTO_TYPE: 'T',
	CONTENT_AREA_ID: 'content_area',
	NO_PHOTO_FILE_NAME: 'nophoto.gif'
};

var ThamesCategoryPreview = {
	body: null,	
	ieAppVersion: null,

	/**
	 * 
	 */
	load: function() {
		var contentAreaElement = null;
		var anchors = null;
		
		//See if we get the elements
		try {
			//Get the body
			ThamesCategoryPreview.body = $$('body').first();
			
			contentAreaElement = $(ThamesCategoryPreviewSettings.CONTENT_AREA_ID);
			
			//Check for missing element
			if(contentAreaElement == null || ThamesCategoryPreview.body == null) {
				return;
			}
			
			/*
			GOING TO BE TOO PROBLEMATIC
			 
		 	Make sure we have the special div that is used in the sort by
			if($('jmenuhide') == null) {
				return;
			}*/
			
			anchors = contentAreaElement.select('a');
			
			//Make sure there are anchors
			if(anchors == null || anchors.size < 1) {
				return null;
			}
						
			//Deal with IE problems
			if (Prototype.Browser.IE) {
				var userAgent = navigator.userAgent;
				var matches = null;
			
				matches = userAgent.match(/MSIE (\d+\.\d+);/);
				if(matches != null && matches.length >= 2) {					
					ThamesCategoryPreview.ieAppVersion = new Number(matches[1]);
					
					new Element('img', {
						src: '/v/thames/images/preview.gif'
					});			
				}				
			}
			
			//Pre-load the preview image	
			new Element('img', {
				src: '/v/thames/images/preview.png'
			});
			
			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 = ThamesCategoryPreview.getProductCodeFromURL(item.readAttribute('href'));			
				if(productCode == null || item.readAttribute('href').toLowerCase().indexOf('shoppingcart.asp') != -1) {
					return;
				}
				
				//Get all the images
				images = item.select('img');
				
				//Must have one image, skip if not
				if(images == null || images.size() != 1) {
					return;
				}
				
				//Special images to skip!
				if(images.first().src.indexOf(ThamesCategoryPreviewSettings.MORE_INFO_FILE_NAME) != -1) {
					return;
				}
				if(images.first().src.indexOf(ThamesCategoryPreviewSettings.NO_PHOTO_FILE_NAME) != -1) {
					return;
				}			
				
				new ThamesCategoryPreviewInitiator(productCode, images.first());
			});
		}
		catch(e) {
			return;
		}				
	},
			
	/**
	 * @return String of product code
	 * @param url is usually location.href
	 */
	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(/.*[\?|&]ProductCode=([^&;]*)/i);	
		if(matches != null && matches.length >= 2) {
			return unescape(matches[1]);
		}
		
		//Check SEO URL
		matches = url.match(/[_-]p\/(.+)\.htm/i);	
		if(matches != null && matches.length >= 2) {
			return unescape(matches[1]);
		}
	
		//No product code available
		return null;
	}	
};

var ThamesCategoryPreviewInitiator = Class.create({
	initialize: function(productCode, imageElement) {
		if(productCode == null || imageElement == null) {
			return;
		}
		
		this.imageElement = imageElement;
		this.productCode = productCode;
		this.mouseMoveEventListener = null;
		this.clickEventListener = null;
		this.overlayElement = null;
		this.previewWindow = null;
		
		//Catch mouse over events
		Event.observe(imageElement, 'mouseover', this.mouseOver.bindAsEventListener(this));
	},
			
	mouseOver: function(event) {
		var elements = null;
		
		//Skip if already an element
		if(this.overlayElement != null) {
			return;
		}

		//Create the element and look for missing items
		elements = this.createOverlay();		
		if(elements == null || elements.main == null | elements.button == null) {
			return null;
		}
		this.overlayElement = elements.main;
		this.buttonElement = elements.button;

		//Watch clicks
		this.clickEventListener = this.click.bindAsEventListener(this);
		Event.observe(this.overlayElement, 'click', this.clickEventListener);
		//Add to the document
		ThamesCategoryPreview.body.insert(this.overlayElement);

		//Position the element
		this.overlayElement.clonePosition(this.imageElement, {setHeight: false, setWidth: false});
		
		//Display
		this.showOverlay();
		
		//Observe for the entire window!
		this.mouseMoveEventListener = this.mouseMove.bindAsEventListener(this);
		Event.observe(ThamesCategoryPreview.body, 'mousemove', this.mouseMoveEventListener);
	},
	
	/**
	 * 
	 */
	showOverlay: function() {
		if(this.overlayElement == null) {
			return;
		}
		
		//Effect.Appear(this.overlayElement, {queue: 'end', duration: 0.4});
		this.overlayElement.show();
	},
	
	/**
	 * 
	 * @param {Object} element
	 */
	hideOverlayAndRemove: function(element) {
		if(element == null) {
			return;
		}

		/*Effect.Fade(element, {queue: 'end', duration: 0.1, afterFinish: function(effect) {
			//Remove the element from the document when done
			if (effect.element != null) {
				effect.element.remove();
			}
		}});*/
		element.hide();
		element.remove();
	},
	
	/**
	 * @return Hash containing both main and button
	 */
	createOverlay: function() {
		var element = null;
		var initiatorButton = null;
		var imgSrc = '/v/thames/images/preview.png';

		//Do not display a PNG for <=IE6
		try {
			if (Prototype.Browser.IE) {
				if(ThamesCategoryPreview.ieAppVersion < 7.0) {
					imgSrc = '/v/thames/images/preview.gif';
				}
			}
		}
		catch(e) {/*Ignore*/}

		element = new Element('div');
		element.addClassName('thames_category_quick_preview_overlay');
		element.setStyle({
			position: 'absolute',
			zIndex: 100,
			display: 'none',
			cursor: 'pointer'
		});
		initiatorButton = new Element('img', {
			src: imgSrc,
			alt: 'Preview',
			title: 'Preview'
		});
		initiatorButton.addClassName('thames_category_quick_preview_overlay_btn');
		element.insert(initiatorButton);
		initiatorButton.setStyle({
			cursor: 'pointer'
		});
				
		return {main: element, button: initiatorButton};
	},
		
	/**
	 * 
	 * @param {Object} event
	 */
	mouseMove: function(event) {
		var x = Event.pointerX(event);
		var y = Event.pointerY(event);
		
		//Skip if no element
		if(this.overlayElement == null) {
			return;
		}
		
		//See if we are still in bounds			
		if( this.boundsCheck(x, y, this.imageElement, this.imageElement.positionedOffset()) ){ 
			return;
		}
		
		//Stop observing events
		if (this.mouseMoveEventListener != null) {
			Event.stopObserving(ThamesCategoryPreview.body, 'mousemove', this.mouseMoveEventListener);
		}
		this.mouseMoveEventListener = null;
		//

		//Call function for mouse out of element		
		this.mouseOut();	
	},	
	
	/**
	 * 
	 */
	mouseOut: function() {
		var overlayElement = this.overlayElement;
		this.overlayElement = null;
		
		if(overlayElement != null) {
			this.hideOverlayAndRemove(overlayElement);
		}
	},
	
	/**
	 * 
	 * @param {Object} x
	 * @param {Object} y
	 * @param {Object} element
	 * @param {Object} elementPosition
	 */
	boundsCheck: function(x, y, element, elementPosition) {
		var position = elementPosition;
		
		var edgeExclusions = {};
		var leftEdge = true;
		var rightEdge = true;
		var topEdge = true;
		var bottomEdge = true;
		
		//Check for an actual element
		if(element == null) {
			return false;
		}
		
		//Extra parameters
		if(arguments[3]) {
			edgeExclusions = arguments[3];
		}
		
		leftEdge = edgeExclusions['excludeLeftEdge'] ? ( x > position.left ) : ( x >= position.left );
		rightEdge = edgeExclusions['excludeRightEdge'] ? ( x < (position.left+element.getWidth()) ) : ( x <= (position.left+element.getWidth()) );
		topEdge = edgeExclusions['excludeTopEdge'] ? (y > position.top) : (y >= position.top);
		bottomEdge = edgeExclusions['excludeBottomEdge'] ? ( y < (position.top+element.getHeight()) ) : ( y <= (position.top+element.getHeight()) );
		
		//Make sure within bounds
		if(leftEdge && rightEdge) {
			if(topEdge && bottomEdge) {
				//Both checkout
				return true;
			}
		}	
		
		//Not within
		return false;
	},	
	
	/**
	 * 
	 * @param {Object} event
	 */
	click: function(event) {
		var thisObj = this;
		var url = null;
		
		//Stop observing events
		if (this.clickEventListener != null && this.overlayElement != null) {
			Event.stopObserving(this.overlayElement, 'click', this.clickEventListener);
		}
		this.clickEventListener = null;
		//

		//Check for existing window first
		if(this.previewWindow != null) {
			//Call function for mouse out of element
			this.mouseOut();
			
			this.previewWindow.load();
			return;
		}

		//Create URL for AJAX call
		url = ThamesCategoryPreviewSettings.GET_PHOTOS_URL;
		
		//Get the data and fire new object
		new Ajax.Request(
			url,
			{
				method: 'get',
				parameters: {
					productCode: escape(this.productCode),
					type: escape(ThamesCategoryPreviewSettings.PHOTO_TYPE)
				},
				evalJSON: true,
				sanitizeJSON: true,
				onCreate: function() {
					thisObj.startShowingWait();
				},
				onSuccess: function(transport) {
					var data = transport.responseJSON;
					
					//Call function for mouse out of element
					thisObj.mouseOut();
					
					//Stop the wait mode
					thisObj.stopShowingWait();					
					
					//No data, just skip
					if(data == null || data.size() <= 0) {
						return;
					}
					
					//Create object and load window
					thisObj.previewWindow = new ThamesCategoryPreviewWindow(thisObj.productCode, thisObj.imageElement, data);
					thisObj.previewWindow.load();
				},
				onFailure: function(e) {
					thisObj.stopShowingWait();
				}
			}
		);		
	},
	
	startShowingWait: function() {
		if (this.imageElement != null) {
			this.imageElement.setStyle({
				cursor: 'wait'
			});
		}
		if (this.overlayElement != null) {
			this.overlayElement.setStyle({
				cursor: 'wait'
			});
			this.buttonElement.setStyle({
				cursor: 'wait'
			});
		}
	},
	
	stopShowingWait: function() {
		if (this.imageElement != null) {
			this.imageElement.setStyle({
				cursor: 'auto'
			});
		}
		if (this.overlayElement != null) {
			this.overlayElement.setStyle({
				cursor: 'pointer'
			});
			this.buttonElement.setStyle({
				cursor: 'pointer'
			});
		}
	}
});

var ThamesCategoryPreviewWindow = Class.create({
	/**
	 * 
	 * @param {Object} productCode
	 * @param {Object} imageElement
	 * @param {Object} data
	 */
	initialize: function(productCode, imageElement, data) {
		var url = null;

		if(productCode == null || imageElement == null || data == null || data.size() <= 0) {
			return;
		}
		
		this.imageElement = imageElement;
		this.productCode = productCode;
		this.data = data;
		this.elements = null;
		this.currentPhotoPosition = 0;
		this.imageElements = [];
		
		//Find maximum width and height
		this.maxPhotoWidth = this.data.max(function(productPhoto){
			return productPhoto.width;
		});
		this.maxPhotoHeight = this.data.max(function(productPhoto){
			return productPhoto.height;
		});				
	},
	
	/**
	 * 
	 */
	load: function() {
		var maxWidth;
		var maxHeight;		
		var element = null;
		var thisObj = this;
		var position = null;
		
		//Skip if already exists
		if(this.elements != null) {
			return;
		}
		
		//Create the window
		this.elements = this.createWindow();
		
		//Add the main element to the body
		element = this.elements.main;				
		ThamesCategoryPreview.body.insert(element);
						
		//Change position based on size
		position = this.imageElement.positionedOffset();
		if (this.isTooWide(position.left, element.getWidth())) {
			
			var leftPosition = (position.left + this.imageElement.getWidth()) - element.getWidth();
			
			element.setStyle({
				top: position.top + 'px',
				left: leftPosition + 'px'
			});
		}
		else {
			element.clonePosition(this.imageElement, {
				setHeight: false,
				setWidth: false
			});
		}
		
		//Create the image elements
		this.data.each(function(photo){
			var imageElement = null;
			var alt = thisObj.imageElement.alt;
			var title = thisObj.imageElement.title;
					
			imageElement = new Element('img', {
				src: ThamesCategoryPreviewSettings.PHOTOS_PATH + '/' + escape(photo.fileName),
				alt: alt,
				title: title
			});
			imageElement.addClassName('thames_category_quick_preview_window_photo');
			
			Event.observe(imageElement, 'click', thisObj.goToProductDetail.bindAsEventListener(thisObj));
			
			thisObj.imageElements.push(imageElement);
		});
		//Show the photo
		this.updatePhoto(this.currentPhotoPosition);
		
		//Setup listeners
		Event.observe(this.elements.close, 'click', this.closeWindow.bindAsEventListener(this));
		//We do not need the add to cart if it is not there, skip it
		if (this.elements.addToCart != null) {
			Event.observe(this.elements.addToCart, 'click', this.addToCart.bindAsEventListener(this));
		}
				
		//Only one image, no need for controls
		if (this.data.size() == 1) {
			this.elements.left.remove();
			this.elements.right.remove();
		}
		else {
			Event.observe(this.elements.left, 'click', this.previousPhoto.bindAsEventListener(this));
			Event.observe(this.elements.right, 'click', this.nextPhoto.bindAsEventListener(this));
		}
		
		//Show the window
		this.showWindow();
	},
	
	/**
	 * 
	 */
	showWindow: function() {
		if(this.elements == null || this.elements.main == null) {
			return;
		}
		
		Effect.Appear(this.elements.main, {queue: 'end', duration: 0.4});
	},
	
	/**
	 * 
	 */
	hideWindowAndRemove: function() {
		if(this.elements == null || this.elements.main == null) {
			return;
		}

		Effect.Fade(this.elements.main, {queue: 'end', duration: 0.4, afterFinish: function(effect) {
			//Remove the element from the document when done
			if (effect.element != null) {
				effect.element.remove();
			}
		}});
	},
	
	/**
	 * 
	 */
	closeWindow: function() {
		if(this.elements == null || this.elements.main == null) {
			return;
		}
		
		//Kill the element
		this.hideWindowAndRemove();
		
		//Reset variables
		this.elements = null;
		this.imageElements = [];
	},
	
	/**
	 * 
	 */
	nextPhoto: function() {
		if(this.elements == null || this.imageElements == null || this.elements.photoContainer == null) {
			return;
		}
		
		//Previous photo
		this.currentPhotoPosition++;
		this.currentPhotoPosition = Math.abs(this.currentPhotoPosition % this.imageElements.size());
		
		//Update the element with the photo
		this.updatePhoto(this.currentPhotoPosition);
	},
	
	/**
	 * 
	 */
	previousPhoto: function() {
		if(this.elements == null || this.imageElements == null || this.elements.photoContainer == null) {
			return;
		}
		
		//Previous photo
		this.currentPhotoPosition--;
		if(this.currentPhotoPosition < 0) {
			this.currentPhotoPosition = this.imageElements.size()-1;
		}
		this.currentPhotoPosition = Math.abs(this.currentPhotoPosition % this.imageElements.size());
		
		//Update the element with the photo
		this.updatePhoto(this.currentPhotoPosition);
	},	
	
	/**
	 * 
	 * @param {Object} index
	 */
	updatePhoto: function(index) {
		//Check for skipping this
		if(this.elements == null || this.elements.photoContainer == null) {
			return;
		}
		if(this.imageElements == null || index >= this.imageElements.size()) {
			return;
		}
		
		//Change the photo
		this.elements.photoContainer.update(this.imageElements[index]);
	},
	
	/**
	 * @return Hash containing main, photoContainer, close, left, right, and addToCart
	 */
	createWindow: function() {
		var element = null;
		var topElement = null;
		var topElementLeft = null;
		var topElementRight = null;
		var middleElement = null;
		var middleElementWrapper = null;
		var bottomElement = null;		
		var leftButton = null;
		var addToCartButton = null;
		var rightButton = null;
		var closeButton = null;
		var dragButton = null;
		
		element = new Element('div');
		element.addClassName('thames_category_quick_preview_window');
		element.setStyle({
			position: 'absolute',
			zIndex: 101,
			opacity: 0,
			display: 'none'
		});		 
		
		topElement = new Element('div');
		topElement.addClassName('thames_category_quick_preview_window_top');
		topElementLeft = new Element('div');
		topElementLeft.addClassName('thames_category_quick_preview_window_top_left');
		topElementRight = new Element('div');
		topElementRight.addClassName('thames_category_quick_preview_window_top_right');
		dragButton = new Element('img', {
			src: '/v/thames/images/drag.gif',
			alt: 'Drag',
			title: 'Drag'
		});
		dragButton.addClassName('thames_category_quick_preview_window_drag_btn');
		closeButton = new Element('input', {
			type: 'image',
			src: '/v/thames/images/close.gif',
			alt: 'Close',
			title: 'Close'
		});
		closeButton.addClassName('thames_category_quick_preview_window_close_btn');
		topElementLeft.insert(dragButton);
		topElementRight.insert(closeButton);
		topElement.insert(topElementLeft);
		topElement.insert(topElementRight);
		
		middleElementWrapper = new Element('div');
		middleElementWrapper.addClassName('thames_category_quick_preview_window_middle');
		middleElement = new Element('div');
		middleElement.setStyle({
			textAlign: 'center'
		});
		//Only set width/height when available
		if(this.maxPhotoWidth != null && this.maxPhotoHeight != null) {
			middleElement.setStyle({
				width: this.maxPhotoWidth +6/*Border*/ + 'px',
				height: this.maxPhotoHeight +6/*Border*/ + 'px'
			});			
		}		
		middleElementWrapper.insert(middleElement);
		
		bottomElement = new Element('div');
		bottomElement.addClassName('thames_category_quick_preview_window_bottom');
		leftButton = new Element('input', {
			type: 'image',
			src: '/v/thames/images/previous.gif',
			alt: 'Previous Photo',
			title: 'Previous Photo'
		});
		leftButton.addClassName('thames_category_quick_preview_window_left_btn');
		addToCartButton = new Element('input', {
			type: 'image',
			src: '/v/thames/images/add_to_cart.gif',
			alt: 'Add To Cart',
			title: 'Add To Cart'
		});
		addToCartButton.addClassName('thames_category_quick_preview_window_add_btn');
		rightButton = new Element('input', {
			type: 'image',
			src: '/v/thames/images/next.gif',
			alt: 'Next Photo',
			title: 'Next Photo'
		});
		rightButton.addClassName('thames_category_quick_preview_window_right_btn');
		bottomElement.insert(leftButton);
		bottomElement.insert(addToCartButton);
		bottomElement.insert(rightButton);
		
		element.insert(topElement);
		element.insert(middleElementWrapper);
		element.insert(bottomElement);
		
		//Make the div draggable
		new Draggable(element, {
			starteffect: null,
			endeffect: null
		});
		
		return {main: element, photoContainer: middleElement, close: closeButton, left: leftButton, right: rightButton, addToCart: addToCartButton};
	},
	
	/**
	 * 
	 * @param {Object} x
	 * @param {Object} width
	 */
	isTooWide: function(x, width) {
		var viewPortWidth = document.viewport.getWidth();
		
		//The view port is just too small for anything
		if(viewPortWidth < width) {
			return false;
		}
		
		//Too wide
		if( (x+width) > viewPortWidth ) {
			return true;
		}
		
		//Just fine
		return false;
	},
	
	/**
	 * 
	 */
	addToCart: function() {
		var template = ThamesCategoryPreviewSettings.ADD_TO_CART_URL_TEMPLATE;
		var url = null;
		
		//Create URL
		url = template.evaluate({
			productCode: escape(this.productCode)
		});
		
		//Redirect
		window.location.href = url;
	},
	
	/**
	 * 
	 */
	goToProductDetail: function() {
		var anchor = this.imageElement.up();
		
		if(anchor != null && anchor.readAttribute('href')) {
			window.location.href = anchor.readAttribute('href');
		}
	}
});
/*--------------------------------------------------------------------------*/