//BySlideMenu
var BySlideMenu = new Class({
	Implements: Options,

	options: {
		defaultIndex: false,
		expandMode: 'mouseover',
		pinMode: false,
		vertical: false,
		compressSize: 40,
		elementWidth: 320,
		elementHeight: 240,
		autoSize: true,
		duration: 500,
		transition: 'linear',
		containerWidth: null,
		containerHeight: null,
		useOverflow: false
	},
	
	initialize: function(containerId, options){
		this.setOptions(options);
		this.elementsId = [];
		this.containerId = $pick(containerId, 'byslidemenu');
		
		var container = $(this.containerId);	
		
		container.addEvent('mouseleave', function(){
			this.resetAll();
		}.bind(this));
		
		var elements = container.getChildren();
		var num = elements.length;

		var imgHeight = null, imgWidth = null;
		if(this.options.autoSize)
		{
			var firstImg = elements[0].getElement('img');
		
			if(firstImg)
			{
				imgHeight = firstImg.getHeight();
				imgWidth = firstImg.getWidth();
			}
		}
		
		var offsetWidth = 
			elements[0].getStyle('padding-left').toInt()
			+ elements[0].getStyle('padding-right').toInt()
			+ elements[0].getStyle('border-left-width').toInt()
			+ elements[0].getStyle('border-right-width').toInt();
		var offsetHeight = 
			elements[0].getStyle('padding-top').toInt()
			+ elements[0].getStyle('padding-bottom').toInt()
			+ elements[0].getStyle('border-top-width').toInt()
			+ elements[0].getStyle('border-bottom-width').toInt();
		
		if(this.options.vertical)
		{
			this.posAttr = 'top';
			var containerWidth = $pick(imgWidth, this.options.containerWidth, this.options.elementWidth);
			if(containerWidth == "full")
				containerWidth = container.getParent().getStyle('width').toInt();
			if(this.options.containerHeight)
			{
				if(this.options.containerWidth == 'full')
					var containerHeight = container.getParent().getStyle('height').toInt();
				else
					var containerHeight = this.options.containerHeight;

				this.openSize = containerHeight - ((num - 1) * this.options.compressSize);
			}
			else
			{
				this.openSize = $pick(imgHeight, this.options.elementHeight);
				var containerHeight = this.openSize + ((num - 1) * this.options.compressSize);
			}
			
			this.closeSize = containerHeight / num;
			
			var elementHeight = this.openSize;
			var elementWidth = containerWidth;
		}
		else
		{
			this.posAttr = 'left';
			var containerHeight = $pick(imgHeight, this.options.containerHeight, this.options.elementHeight);
			if(containerHeight == "full")
				containerHeight = container.getParent().getStyle('height').toInt();
			if(this.options.containerWidth)
			{
				if(this.options.containerWidth == 'full')
					var containerWidth = container.getParent().getStyle('width').toInt();
				else
					var containerWidth = this.options.containerWidth;

				this.openSize = containerWidth - ((num - 1) * this.options.compressSize);
			}
			else
			{
				this.openSize = $pick(imgWidth, this.options.elementWidth);
				var containerWidth = this.openSize + ((num - 1) * this.options.compressSize);
			}
			this.closeSize = containerWidth / num;
			
			var elementHeight = containerHeight;
			var elementWidth = this.openSize;
		}

		container.setStyles({
			padding: 0,
			position: 'relative',
			overflow: 'hidden',
			width: containerWidth,
			height: containerHeight
		});
		
		var id = 0;
		
		elements.each(function(element){
			var beforePos = id * this.options.compressSize;
			var afterPos = this.openSize + ((id - 1) * this.options.compressSize);
			var closePos = id * this.closeSize;
			element.setStyles({
				position: 'absolute',
				height: elementHeight - offsetHeight,
				width: elementWidth - offsetWidth
			});
			element.setStyle(this.posAttr, closePos);
			element.set('tween', {
				duration: this.options.duration,
				transition: this.options.transition
			});
			
			id++;
			
			element.set('id', this.containerId + '_Elm' + id);
			element.store('id', id);
			
			element.store('beforePos', beforePos);
			element.store('afterPos', afterPos);
			element.store('closePos', closePos);

			this.elementsId.include(id);
			
			if([this.options.pinMode, this.options.expandMode].contains('mouseover'))
			{
				element.addEvent('mouseenter', function(element){
					if(this.options.expandMode == 'mouseover')
						this.expand(element, this.options.pinMode == 'mouseover');
				}.bind(this, element));
			}
			
			if(this.options.pinMode || this.options.expandMode == 'click')
			{
				element.addEvent('click', function(element){
					if(this.options.defaultIndex == element.retrieve('id'))
					{
						this.options.defaultIndex = 0;
						this.resetAll();
					}
					else if(this.options.expandMode == 'click')
						this.expand(element, this.options.pinMode == 'click');
					else
						this.options.defaultIndex = element.retrieve('id');
				}.bind(this, element));
			}

		}, this);
		
		if(this.options.defaultIndex)
			this.expand(this.options.defaultIndex, false, true);
	},
	
	expand: function(element, setDefault, noAnim){
		if($type(element) == 'number')
			element = $(this.containerId + '_Elm' + element);
			
		if(this.options.useOverflow)
			this.clearOverflow();
		
		var currentId = element.retrieve('id');
		
		if(this.options.useOverflow)
			this.switchOverflowTimer = this.switchOverflow.delay(this.options.duration, this, element);
		
		if(setDefault)
			this.options.defaultIndex = currentId;
		
		this.elementsId.each(function(elementId){
			var elm = $(this.containerId + '_Elm' + elementId);
			if(elementId > currentId)
				this.compressAfter(elm, noAnim);
			else
				this.compressBefore(elm, noAnim);
		}, this);
	},
	
	switchOverflow: function(element){
		element.setStyle('overflow', 'auto');
	},
	
	clearOverflow: function(){
		$clear(this.switchOverflowTimer);
		$(this.containerId).getChildren().setStyle('overflow', '');
	},
	
	compressBefore: function(element, noAnim){
		var pos = element.retrieve('beforePos');
		var tween = element.get('tween', {property: this.posAttr, duration: this.options.duration, transition: this.options.transition});
		
		if(noAnim)
			tween.set(pos);
		else
			tween.start(pos);
	},
	
	compressAfter: function(element, noAnim){
		var pos = element.retrieve('afterPos');
		var tween = element.get('tween', {property: this.posAttr, duration: this.options.duration, transition: this.options.transition});
		if(noAnim)
			tween.set(pos);
		else
			tween.start(pos);
	},
	
	reset: function(element){
		var pos = element.retrieve('closePos');
		element.get('tween', {property: this.posAttr, duration: this.options.duration, transition: this.options.transition}).start(pos);
	},
	
	resetAll: function(){
		if(this.options.useOverflow)
			this.clearOverflow();

		if(this.options.defaultIndex)
			this.expand(this.options.defaultIndex);
		else
		{
			this.elementsId.each(function(elementId){
				this.reset($(this.containerId + '_Elm' + elementId));
			}, this);
		}
	}
});

/**
 * ToolTips - show tooltips on hover
 * @version		0.1
 * @MooTools version 1.2.1
 * @author		Constantin Boiangiu <info [at] constantinb.com>
 */

var MooTooltips = new Class({
	
	Implements: [Options],
	
	options: {		
		container: null,	// hovered elements
		hovered:null,		// the element that when hovered shows the tip
		extra:null,
		ToolTipClass:'ToolTips',	// tooltip display class
		toolTipPosition:1, // -1 top; 1: bottom
		showDelay: 500,
		sticky:false,		// remove tooltip if closed
		fromTop: 0,		// distance from mouse or object
		fromLeft: 0,
		duration: 100,		// fade effect transition duration
		fadeDistance: 20    // the distance the tooltip starts fading in/out
	},
	
	initialize: function(options) {
		this.setOptions(options||null);
		if(!this.options.hovered && !this.options.extra) return;	
		
		if( this.options.hovered )
			this.elements = $(this.options.container||document.body).getElements(this.options.hovered);
		
		if(!$defined(this.elements)) this.elements = new Array();
		
		var e = new Hash(this.options.extra);
		e.each(function(el){
			$(el.id).set( 'rel', JSON.encode(el) );
			this.elements.include($(el.id));			
		},this);
		
		this.currentElement = null;
		this.attach();
	},
	
	attach: function(){
		this.elements.each(function(elem, key){
			var t = new Hash(JSON.decode(elem.getProperty('rel')));
			t.include('visible',0);
			
			var tooltip = this.createContainer(t.sticky||this.options.sticky);
			/* 
				set the tooltip content.  
				depending on where the content is, set the according parameters.
				
				Parameters for every element are:
				- content: element id to get the tip content from a HTML element ( a div within the page for example )
				- text: just input some text directly into the parameter and there you have it
				- ajax: get the content from a remote page				
			*/
			if( t.content )
				tooltip.message.set({'html':$(t.content).get('html')});
			else if( t.text )
				tooltip.message.set({'html':t.text});
			else if( t.ajax ){
				tooltip.message.set({'html':t.ajax_message||'Loading... please wait.'});
				new Element('div', {'class':'loading'}).injectInside(tooltip.message);
				/* the actual ajax call is made when element is hovered */
			}				
			/*
				by default, the tooltip is positioned below the element.
				if placed above, the script switches the CSS classes on the footer and header
				to make it point at the element hovered
			*/
			if( !t.position ) t.position = this.options.toolTipPosition;
			if( t.position == -1 ){
				tooltip.header.set({'class':'dockTopHeader'});
				tooltip.footer.set({'class':'dockTopFooter'});
			}
			
			tooltip.container.store('properties', t);
			elem.store('tip', tooltip.container);
			$(document.body).adopt(tooltip.container);
			elem.removeProperties('title','rel');
			
			var over = this.enter.bindWithEvent(this, elem);
			var out = this.leave.bindWithEvent(this, elem);
			elem.addEvent('mouseover', over);
			if( t.sticky || this.options.sticky){
				tooltip.close.addEvent('click', this.hide.pass(tooltip.container).bind(this)  );
			}
			elem.addEvent('mouseleave', out.pass(tooltip.container));				
			
		}, this);
	},
	
	enter: function(event, element){
		var tip = element.retrieve('tip');		
		/* all the tip properties are stored on the element */
		var elProperties = tip.retrieve('properties');
		if(elProperties.visible == 1) return;
		
		if( elProperties.ajax && !elProperties.loaded ){
			new Request.HTML({
				url: elProperties.ajax, 
				update: tip.getElement('.message'),
				/* if loading fails, set the loaded propety back to false so when the element is hovered, a new request is made */
				onFailure: function(){
					elProperties.set('loaded',0);
				}
			}).get();
			/* 
				set it as loaded when user hovers the element. 
				This way, while loading, if the user hovers the element again, it will not make a new request 
			*/
			elProperties.set('loaded',1);
		}
		
		/* if property target set on element, show tooltip after target */	
		var showAfter = elProperties.target ? $(elProperties.target) : element;
		var elSize = showAfter.getCoordinates();
		var tipSize = tip.getCoordinates();
		
		this.fromTop = 0;
		if( elProperties.position == -1 )
			this.fromTop = elSize.top - this.options.fromTop - tipSize.height;
		else
			this.fromTop = elSize.top + this.options.fromTop + elSize.height;
		
		var top_dist = this.fromTop + (elProperties.position||this.options.toolTipPosition) * this.options.fadeDistance ;
		
		tip.setStyles({
			'top': top_dist,
			'left': elSize.left + this.options.fromLeft,			
			'z-index':'110000'
		});		
		
		elProperties.set('leave', top_dist);		
		this.currentElement = tip;
		this.timer = $clear(this.timer);
		this.timer = this.show.delay(this.options.showDelay, this);
	},
	
	leave: function(element){
		var elProperties = element.retrieve('properties');
		/* if tooltip is visible and sticky, it closes when close button is clicked */
		if( (elProperties.sticky || this.options.sticky) && elProperties.visible ){
			return;	
		}
		this.hide(element);
	},
	
	hide: function(element){
		this.timer = $clear(this.timer);		
		var elProperties = element.retrieve('properties');
		element.morph({'opacity':0,'top': elProperties.leave});
		elProperties.visible = 0;
	},
	
	show: function(){
		this.currentElement.setStyles({'display':'block','opacity':0,'z-index':100000});
		this.currentElement.morph({'opacity':1, 'top':this.fromTop});		
		//this.setVisible.delay(this.options.duration, this);
		this.setVisible();
	},
	
	setVisible: function(){
		var elProperties = this.currentElement.retrieve('properties');
		elProperties.visible = 1;				
	},
	
	createContainer: function( sticky ){
		var container = new Element('div').set({
			'class':this.options.ToolTipClass, 
			'styles':{ 
				'position':'absolute',
				'top':0,
				'left':0,
				'opacity':0,
				'z-index':'100000' 
			},
			'morph':{
				duration:this.options.duration, 
				link:'cancel', 
				transition:Fx.Transitions.Sine.easeOut
			}
		});
		var header = new Element('div', {'class':'dockBottomHeader'});
		if( sticky ){
			var closeBtn = new Element('div', { 'class':'sticky_close' }).injectInside(header);
		}	
		var message = new Element('div', {'class':'message'});
		var footer = new Element('div', {'class':'dockBottomFooter'});
		container.adopt( header, message, footer );
		
		return {'container':container,'header':header,'message':message,'footer':footer,'close':closeBtn||null};		
	}	
});