var ForzieriAdvisor = new Class({
	Implements: [Options, Events],
	
	elementId: {},
	
	elements: {
		advisor: null,
		overlay: null,
		content: null,
		contentLoader: null,
		tableContainer: null,
		closeButton: null
	},
	
	html: {
		advisorTable: '<table class="advisorTable"><tr><td class="topleft png"></td><td class="top png"></td><td class="topright png"></td></tr><tr><td class="left png"></td><td><div class="center png"></div></td><td class="right png"></td></tr><tr><td class="bottomleft png"></td><td class="bottom png"></td><td class="bottomright png"></td></tr></table>',
		advisorOkButton: '<a class="btn advisorOkButton" href="#"><span>Ok</span></a>',
		advisorCancelButton: '<a class="btn advisorCancelButton" href="#"><span>Cancel</span></a>'
	},
	
	contentLoaded: false,
	
	/* Initialization
	Options:
	- method: for loading content: get or post
	- width: the width of the content section of the Advisor
	- contentURL: the URL for the content to show
	- elementToAlign: a Mootools Element. This will be the referred element for the popup positioning
	- appearPositionX: 'top' or 'left' based to the elementToAlign
	- appearPositionY: 'left' or 'right' based to the elementToAlign
	- customNavigation: BOOL, if false, show the standard ok, cancel buttons
	- okButtonText: STRING, text for the OK button, used only if customNavigation is true
	- cancelButtonText: STRING, text for the cancel button, used only if customNavigation is true
	- theme: STRING, the class of the new theme. Default is 'default'
	- overlayTheme: STRING, the class for the overlay theme. Default is 'default'
	- useOverlay: BOOL for use of an Overlay
	- overlayOpacity: FLOAT, 
	- centerVertically: BOOL. If the popup will be centered vertically
	- closeButton: BOOL, if true, show the close button at the right/top
	- destroyOnClose: BOOL, if set to false, the advisor is only hidden when the close button is clicked otherwise it is destroyed completely
	*/
	options: {
		id: 'Advisor',
		method: 'get',
		width: '100%',
		height: '100%',
		contentURL: '',
		elementToAlign: null,
		appearPositionX: 'right',
		appearPositionY: 'top',
		customNavigation: false,
		okButtonText: 'OK',
		cancelButtonText: 'Cancel',
		theme: 'default',
		overlayTheme: 'default',
		useOverlay: true,
		overlayOpacity: 0.75,
		centerVertically: true,
		closeButton: true,
		escKey: true,
		destroyOnClose: false,
		showOnLoad: true
	},
	
	
	initialize: function(options) {
		this.setOptions(options);
		
		this.elementId = {
			advisor: this.options.theme + this.options.id,
			overlay: this.options.theme + this.options.id + 'Overlay',
			content: this.options.theme + this.options.id + 'Content',
			contentLoader: this.options.theme + this.options.id + 'ContentLoader'
		};
		
		this.createOverlay();
		this.createAdvisor();
		this.createContent();
		this.createEvents();
		
		this.show();
	},
	
	show: function() {
		if ( this.contentLoaded ) {
			this.showAdvisor();
		} else {
			this.loadContent();
		}
	},
	
	loadContent: function() {
		var self = this;
		
		// fetch the content via ajax
		var request = new Request.HTML({
			method: this.options.method,
			url: this.options.contentURL,
			evalScripts: true,
			update: this.elements.content,
			onSuccess: function() {
				self.fireEvent('contentLoaded');
			},
			onFailure: function(xhr) {
				self.fireEvent('error', 'Failure Error! Try Again Later.');
			},
			onException: function(headerName, value) {
				self.fireEvent('error', 'Exception Error! Try Again Later.');
			}
		}).send();
	},
	
	onContentLoaded: function() {
		
		this.contentLoaded = true;
		
		this.createCloseButton();
		this.setCustomNavigation();
		
		// parse Facebook XFBML if FB is loaded
		Facebook.parse(this.elements.content);
		
		this.positionAdvisor();
		
		if ( this.options.showOnLoad ) {
			this.showAdvisor();
		}
	},
	
	positionAdvisor: function() {
		// for easy reference
		var table = this.elements.advisor.getElements('.advisorTable')[0];
		var el = $(this.options.elementToAlign);
		
		// align advisor to a specific element
		if ( el != null ) {
			
			this.elements.advisor.setStyles({
				'position': 'absolute',
				'width': 'auto'
			});
			
			table.setStyle('position', 'relative');
			
			if ( Browser.Engine.trident4 ) {
				table.setStyles({
					position: 'absolute',
					width: this.options.width
				});
			}
			
			var elementCoords = el.getCoordinates();
			var tableCoords = table.measure(function(){return this.getCoordinates();});
			
			switch(this.options.appearPositionX) {
				case 'left':
					table.setStyles({
						left: elementCoords.left,
						margin: 0
					});
				break;
				
				case 'center':
					table.setStyles({
						left: elementCoords.left - (tableCoords.width / 2) - (elementCoords.width / 2),
						margin: 0
					});
				break;
				
				case 'right':
					table.setStyles({
						left: elementCoords.left - (tableCoords.width - elementCoords.width),
						margin: 0
					});
				break;
			}
			
			switch(this.options.appearPositionY) {
				case 'top':
					table.setStyle( 'top', elementCoords.top - tableCoords.height );
				break;
				
				case 'bottom':
					table.setStyle( 'top', elementCoords.top + elementCoords.height );
				break;
			}
			
		}
		
		// centering vertically, only if required
		if ( this.options.centerVertically )
		{
			// use measure() for IE6 compatibility
			var posY = table.measure(function() {
				var height = this.getCoordinates().height;
				var windowHeight = $(window).getSize().y;
				return (windowHeight/2) - (height/2);
			});
			table.setStyle('top', posY);
		}
	},
	
	showAdvisor: function() {
		var self = this;
		
		Tools.hideAllSelects();
		this.elements.content.getElements('select').setStyle('visibility', 'visible');
		this.elements.advisor
			.setStyles({
				display: 'block',
				visibility: 'visible'
			})
			.set('tween', {
					duration: 'short',
					onComplete: function() {
						this.removeEvents('complete');
						self.fireEvent('show');
					}
				})
			.tween('opacity', 1);
		
		if (this.options.useOverlay) {
			this.elements.overlay
				.setStyles({
					display: 'block',
					visibility: 'visible'
				})
				.set('tween', {duration: 'short'})
				.tween('opacity', this.options.overlayOpacity);
		}
	},
	
	hide: function() {
		var self = this;
		
		// advisor animation
		this.elements.advisor
			.set('tween', {
					duration: 'short',
					onComplete: function() {
						this.removeEvents('complete');
						this.element.hide();
						Tools.showAllSelects();
						self.fireEvent('hide');
					}
				})
			.tween('opacity', 0);
		
		// overlay animation
		if (this.options.useOverlay)
		{
			this.elements.overlay
				.set('tween', {
						duration: 'short',
						onComplete: function() {
							this.removeEvents('complete');
							this.element.hide();
						}
					})
				.tween('opacity', 0);
		}
	},
	
	createOverlay: function() {
		if ( this.options.useOverlay )
		{
			this.elements.overlay = new Element('div', {
				'id': this.elementId.overlay,
				'class': this.options.overlayTheme + 'Overlay advisorOverlay',
				'styles': {
					'opacity': this.options.overlayOpacity,
					'height': $$('html').getScrollSize()[0].y
				}
			});
			
			// Put Advisor Overlay Div at the top of the Body
			this.elements.overlay.inject($(document.body), 'top');
		}
	},
	
	destroyOverlay: function() {
		if ( this.options.useOverlay ) {
			this.elements.overlay.destroy();
		}
	},
	
	createAdvisor: function() {
		// create the advisor div
		this.elements.advisor = new Element('div', {
			'id': this.elementId.advisor,
			'html': this.html.advisorTable,
			'class': 'advisor ' + this.options.theme
		}).inject($(document.body), 'top');
	},
	
	destroyAdvisor: function() {
		this.elements.advisor.destroy();
		this.destroyOverlay();
		this.fireEvent('close');
	},
	
	createContent: function() {
		this.elements.tableContainer = this.elements.advisor.getElements('.advisorTable div.center')[0];
		this.elements.tableContainer.setStyle('width', this.options.width);
		
		// create the content loader div
		this.elements.contentLoader = new Element('div', {
			'id': this.elementId.contentLoader,
			'class': 'advisorContentLoader'
		}).inject(this.elements.tableContainer);
		
		// create the advisor content div - content will be loaded into this container
		this.elements.content = new Element('div', {
			'id': this.elementId.content,
			'class': 'advisorContent'
		}).inject(this.elements.tableContainer);
	},
	
	createCloseButton: function() {
		if (this.options.closeButton) {
			var self = this;
			this.elements.closeButton = new Element('a', {
				'href': '#',
				'html': 'Close',
				'class': 'advisorCloseButton png',
				'events': {
					'click': function(e){
						e.preventDefault();
						self.fireEvent('closeButton');
					}
				}
			}).inject(this.elements.content, 'after');
		}
	},
	
	setCustomNavigation: function() {
		// if we are not using custom navigation, insert the standard ok/cancel buttons
		if ( !this.options.customNavigation ) {
			this.createButtons();
			this.createButtonEvents();
		}
	},
	
	createButtons: function() {
		this.elements.buttons = new Element('div', {
			'class': 'advisorNavigation',
			'html': this.html.advisorOkButton + this.html.advisorCancelButton
		}).inject(this.elements.content, 'bottom');
		
		this.elements.buttons.getElements('.advisorOkButton span').set('html', this.options.okButtonText);
		this.elements.buttons.getElements('.advisorCancelButton span').set('html', this.options.cancelButtonText);
	},
	
	createButtonEvents: function() {
		var self = this;
		
		this.elements.buttons.getElements('.advisorOkButton').addEvent('click', function(e) {
			e.preventDefault();
			self.fireEvent('okButton', this);
		});
		
		this.elements.buttons.getElements('.advisorCancelButton').addEvent('click', function(e) {
			e.preventDefault();
			self.fireEvent('cancelButton', this);
		});
	},
	
	createEvents: function() {
		var self = this;
		
		this.addEvents({
			contentLoaded: function() { self.onContentLoaded(); },
			show: function() { self.onShow(); },
			hide: function() { self.onHide(); },
			close: function() { self.onClose(); },
			okButton: function(btn) { self.onOkButton(btn); },
			cancelButton: function(btn) { self.onCancelButton(btn); },
			closeButton: function(btn) { self.onCloseButton(btn); },
			error: function(msg) { self.onError(msg); }
		});
		
		$(document).addEvent('keydown', function(event) {
			self.onKeydown(event);
		});
	},
	
	onShow: function() {
	},
	
	onHide: function() {
		if ( this.options.destroyOnClose ) {
			this.destroyAdvisor();
		}
	},
	
	onClose: function() {
		this.contentLoaded = false;
	},
	
	onOkButton: function(btn) {
	},
	
	onCancelButton: function(btn) {
		this.hide();
	},
	
	onCloseButton: function(btn) {
		this.hide();
	},
	
	onKeydown: function(event) {
		if ( this.options.escKey && event.key == 'esc' ) this.hide();
	},
	
	onError: function(msg) {
		this.destroyAdvisor();
	}
});




var ForzieriIFrameAdvisor = new Class({
	Extends: ForzieriAdvisor,
	
	initialize: function(options) {
		this.parent(options);
	},
	
	show: function() {
		if ( !this.contentLoaded ) {
			this.createIFrame();
		}
		
		this.createCloseButton();
		
		this.positionAdvisor();
		this.showAdvisor();
	},
	
	createIFrame: function() {
		var windowheight = $(window).getSize().y;
		
		if ( this.options.height.indexOf('%') != -1 ) {
			this.options.height = Math.round(parseInt(this.options.height, 10) * windowheight / 100);
		}
		
		this.elements.iframe = new Element('iframe', {
			id: 'advisorIFrame',
			src: this.options.contentURL + '&layout=1',
			width: this.options.width,
			height: this.options.height,
			scrolling: 'no',
			frameborder: 0,
			events: {
				load: function() {
					this.fireEvent('contentLoaded');
				}.bind(this)
			}
		}).inject(this.elements.content);
	},
	
	onContentLoaded: function() {
		this.contentLoaded = true;
		this.createScroller();
	},
	
	createScroller: function() {
		
		// check to see if we need to scroll this window
		this.scroll = this.elements.iframe.contentWindow.document.getScrollSize();
		
		if ( scroll.y <= this.options.height ) return;
		
		this.createScrollbar();
		this.createSlider();
	},
	
	createScrollbar: function() {
		this.elements.scrollbar = new Element('div', {
			'class': 'fz_scroller_scrollbar fz_scroller_scrollbar_v'
		});
		
		this.elements.handle = new Element('div', {
			'class': 'fz_scroller_handle fz_scroller_handle_v'
		}).inject(this.elements.scrollbar);
		
		this.elements.content.addClass('fz_scroller fz_scroller_scrollable');
		
		new Element('div.advisor_scrollbar.png')
			.grab( this.elements.scrollbar )
			.inject( this.elements.content );
	},
	
	createSlider: function() {
		var self = this,
			steps;
		
		steps =  this.scroll.y - this.options.height;
		
		this.elements.slider = new Slider(this.elements.scrollbar, this.elements.handle, {
			steps: steps,
			mode: 'vertical',
			wheel: true,
			onChange: function(step) {
				// scrolls the content of the mask in x or y direction.
				self.elements.iframe.contentWindow.scrollTo(0, step);
			}
		});
		
		// scroll the content element when the mousewheel is used within the content or the scrollbar element
		this.elements.iframe.contentWindow.document.addEvents({
			mousewheel: function(e) {
				e = new Event(e).stop();
				var step = self.elements.slider.step - e.wheel * 30;
				self.elements.slider.set(step);
			},
			resize: function() {
				// document.resize is not a standard browser event. it is a custom event fired by the tabs class
				self.resetSlider();
			}
		});
		this.elements.iframe.contentWindow.addEvents({
		});
		// stop the handle dragging process when the mouse leaves the document body
		$(document.body).addEvent('mouseleave', function() { self.elements.slider.drag.stop(); });
	},
	
	resetSlider: function() {
		if ( this.elements.scrollbar ) {
			this.elements.slider.detach();
			this.elements.scrollbar.destroy();
		}
		this.createScroller();
	}
});



var ForzieriHelpAdvisor = new Class({
	Extends: ForzieriIFrameAdvisor,
	
	initialize: function(options) {
		this.parent(options);
		
		this.addEvent('contentLoaded', function() {
			this.createLinks();
		}.bind(this));
	},
	
	createLinks: function() {
		var self = this;
		
		this.elements.links = new Element('ul.advisor_links', { children: [
			new Element('li', { children: [
				new Element('a', {
					href: this.options.contentURL,
					text: Messages.msg_need_more_help
				})
			]}),
			
			new Element('li', { children: [
				new Element('a', {
					href: '#',
					text: Messages.msg_back_to_product,
					events: {
						click: function(e) {
							e.preventDefault();
							self.hide();
						}
					}
				})
			]})
		]}).inject( this.elements.content );
	}
});
