/**
 * 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: 0,
		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();

		var top_dist = elSize.top + this.options.fromTop ;
		var lft_dist = elSize.left + this.options.fromLeft;

		var screen={
			top:0,
			left:0,
			width:0,
			height:0
		};

		if( typeof( window.innerWidth ) == 'number' ) {
			//Non-IE
			screen.width = window.innerWidth;
			screen.height = window.innerHeight;
		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
			//IE 6+ in 'standards compliant mode'
			screen.width = document.documentElement.clientWidth;
			screen.height = document.documentElement.clientHeight;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
			//IE 4 compatible
			screen.width = document.body.clientWidth;
			screen.height = document.body.clientHeight;
		}

		if( typeof( window.pageYOffset ) == 'number' ) {
			//Netscape compliant
			screen.top = window.pageYOffset;
			screen.left = window.pageXOffset;
		} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
			//DOM compliant
			screen.top = document.body.scrollTop;
			screen.left = document.body.scrollLeft;
		} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
			//IE6 standards compliant mode
			screen.top = document.documentElement.scrollTop;
			screen.left = document.documentElement.scrollLeft;
		}
		screen.width=screen.left+screen.width;
		screen.height=screen.top+screen.height;

		// определение x
		var xMiddle=false;
		if ((lft_dist+tipSize.width)>elSize.left && lft_dist<elSize.left) {
			lft_dist=elSize.left+elSize.width+5;
		}
		if ((lft_dist+tipSize.width)>screen.width) {
			lft_dist=elSize.left-tipSize.width-5;
		}
		if (lft_dist<screen.left) {
			lft_dist=screen.left;
		}
		if ((lft_dist+tipSize.width)>elSize.left && lft_dist<elSize.left) {
			lft_dist=Math.round(screen.left+(screen.width-screen.left)/2-tipSize.width/2);
			xMiddle=true;
		}

		// определение y
		this.fromTop = 0;
		if ((top_dist+tipSize.height)>elSize.top && xMiddle && top_dist<elSize.top) {
			top_dist=elSize.top+elSize.height+5;
		}
		if ((top_dist+tipSize.height)>screen.height) {
			if (xMiddle==false) {
				top_dist=screen.height-tipSize.height-5;
			} else {
				top_dist=elSize.top-tipSize.height-5;
			}
		}
		if (top_dist<screen.top) {
			if (xMiddle==false || (screen.top+5+tipSize.height)<elSize.top) {
				top_dist=screen.top+5;
			} else {
				top_dist=elSize.top+elSize.height+5;
			}
		}
		if (top_dist<screen.top && xMiddle && top_dist<elSize.top) {
			top_dist=screen.top;
			xMiddle=-1;
		}

		//
		this.fromTop=top_dist;
		if ((top_dist+this.options.fadeDistance)<elSize.top) {
			top_dist=top_dist-this.options.fadeDistance;
			this.options.toolTipPosition=-1;
		} else {
			top_dist=top_dist+this.options.fadeDistance;
			this.options.toolTipPosition=1;
		}

		top_dist = top_dist + this.options.toolTipPosition * this.options.fadeDistance ;

		tip.setStyles({
			'top':	top_dist,
			'left':	lft_dist,
			'z-index':'110000'
		});

		if (xMiddle==-1) {
			return;
		}

		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,
				wait: false,
				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};
	}
});
