var tooltips = new Object();
tooltips.urbantooltip = '<div class="urban_tooltip"></div>';
//tooltips.bubble = '<div class="bubble"><div class="left top_left fixpng"><div class="right top_right fixpng"></div></div><div class="left middle_left"><div class="right middle_right content">Content...</div></div><div class="left bottom_left fixpng"><div class="right bottom_right fixpng"></div></div><div class="tip fixpng"></div></div>';

tooltips.bubble = '<div class="bubble"><div class="left top_left iepng"><div class="right top_right iepng"></div></div><div class="left middle_left"><div class="right middle_right content">Content...</div></div><div class="left bottom_left iepng"><div class="right bottom_right iepng"></div></div><div class="tip iepng"></div></div>';

window.disableTooltips = false;

Element.implement({

    getScrollPosition: function(fn) {
        var left = 0,
            top = 0,
            safari = window.webkit,
            safari2 = window.webkit419,
            mozilla = window.gecko,
            parent = this.parentNode,
            offsetChild = this,
            offsetParent = this.offsetParent,
            doc = this.ownerDocument,
            css = Element.getComputedStyle,
            fixed = this.getStyle('position') == 'fixed';

        function border(el) {
            add(el.getStyle('border-left-width'), el.getStyle('border-top-width'));
        }

		function add(l, t) {
		    left += Math.round(parseFloat(l, 10) || 0);
		    top += Math.round(parseFloat(t, 10) || 0);
		}

        if (!(mozilla && this == doc.body) && this.getBoundingClientRect) {
            var box = this.getBoundingClientRect();
            add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
				box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
            add(-doc.documentElement.clientLeft, -doc.documentElement.clientTop);
        } else {
            add(this.offsetLeft, this.offsetTop);
            while (offsetParent) {
                add(offsetParent.offsetLeft, offsetParent.offsetTop);
                if (mozilla && !(/^t(able|d|h)$/i).test(offsetParent.tagName) || safari && !safari2)
                    border(offsetParent);
                if (!fixed && offsetParent.getStyle('position') == 'fixed')
                    fixed = true;
                offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
                offsetParent = offsetParent.offsetParent;
            }
            while (parent && parent.tagName && !(/^body|html$/i).test(parent.tagName)) {
                if (!(/^inline|table.*$/i).test(parent.getStyle('display'))) add(-parent.scrollLeft, -parent.scrollTop);
                if (mozilla && parent.getStyle('overflow') != 'visible') border(parent);
                parent = parent.parentNode;
            }
            if ((safari2 && (fixed || offsetChild.getStyle('position') == 'absolute')) ||
				(mozilla && offsetChild.getStyle('position') != 'absolute'))
                add(-doc.body.offsetLeft, -doc.body.offsetTop);
            if (fixed)
                add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
					Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
        }
        return { x: left, y: top };
    }
});



var Tooltip = Element.implement({

	injectHTMLInside: function(content)
	{
		var child = new Element('div').set('html', content).getChildren();
		child[0].inject(this, 'inside');
		return child[0];
	},
	
	injectHTMLBefore: function(content)
	{
		var child = new Element('div').set('html', content).getChildren();
		child[0].inject(this, 'before');
		return child[0];
	},

	createTooltip: function(callback)
	{
		if ( !this.tooltip )
		{
			this.tooltip = document.getElement('body').injectHTMLInside( tooltips[this.element] );
			this.tooltip.setStyles({
				'position':'absolute',
				'z-index': URBAN.page.toolbox.getNextHighestZindex(),
				'visibility': 'hidden',
				'opacity': 0
			});
			
			if(this.extraClass)
			{
				this.tooltip.addClass(this.extraClass);
			}

			this.setTooltipContent(this.tooltipText);
			
			if($chk(callback))
			{
				callback();
			}
			
			return this;
		}
	},
	
	stickTooltip: function(sticky)
	{
		if ( this.fxInProgress ) return this;
		
		this.sticky = ( sticky == undefined ? true : sticky );
		return this;
	},
	
	unStickTooltip: function()
	{
		if ( this.fxInProgress ) return this;
		
		this.stickTooltip(false);
		return this;
	},

	disableTooltip: function(disable)
	{
		if ( this.fxInProgress ) return this;
		
		this.disable = ( disable == undefined ? true : disable );
		return this;		
	},
	
	enableTooltip: function()
	{
		if ( this.fxInProgress ) return this;
		
		this.disableTooltip(false);
		return this;
	},

	showTooltip: function(event)
	{	
		if ( this.disable || window.disableTooltips ) return this;
		
		if( !$chk(this.tooltip) )
		{
			var element = this;
			return this.createTooltip(function(){ element.showTooltip(); });
		}
		
		if ( this.fxInProgress || this.sticky )
		{
			this.requestedState = 1;
			return this;
		}
		
		if( $chk(this.getProperty('title')) && this.tooltipText != this.getProperty('title'))
		{
			this.tooltipText = this.getProperty('title');
			this.removeProperty('title');
		}

		this.tooltipPosition = this.getTooltipPosition(this.arrayPosition);
		
		this.tooltipFx = new Fx.Morph(this.tooltip, {
			'duration': 500,
			'wait': false,
			'transition': Fx.Transitions.Back.easeOut,
			onStart: function()
			{
				this.fireEvent('tooltipwillshow', this);
				this.requestedState = 0;
				this.fxInProgress = true;
				this.tooltip.setStyles({
					'left': this.tooltipPosition.fxLeft,
					'top': this.tooltipPosition.fxTop
				});
			}.bind(this),
			onComplete: function()
			{
				this.fireEvent('tooltiphasshow', this);
				this.fxInProgress = false;
				if ( this.requestedState == -1 ) this.hideTooltip();
			}.bind(this)
		}).start({
			'top': [this.tooltipPosition.fxTop, this.tooltipPosition.top],
			'left': [this.tooltipPosition.fxLeft, this.tooltipPosition.left],
			'opacity': [0, 1]
		});
		return this;
	},

	hideTooltip: function(event)
	{	
		if ( this.sticky )
		{
			this.requestedState = 1;
			return this;
		}
		
		if ( this.fxInProgress )
		{
			this.requestedState = -1;
			return this;
		}
		
		if(this.tooltipPosition)
		{
			this.tooltipFx = new Fx.Morph(this.tooltip, {'duration':500,
				'wait':false,
				'transition': Fx.Transitions.Back.easeOut,
				onStart: function()
				{
					this.fireEvent('tooltipwillhide', this);
					this.requestedState = 0;
					this.fxInProgress = true;
				}.bind(this),
				onComplete: function()
				{
					this.fireEvent('tooltiphashide', this);
					this.fxInProgress = false;
					if ( this.requestedState == 1 ) this.showTooltip();
				}.bind(this)
			}).start({
				'top': [this.tooltipPosition.top, this.tooltipPosition.fxTop],
				'left': [this.tooltipPosition.left, this.tooltipPosition.fxLeft],
				'opacity': ['1', '0']
			});
		}
		return this;
	},
	
	getTooltipAppearEvent: function()
	{
		if($chk(this.appearEvent))
		{
			return this.appearEvent;
		}
		else
		{
			switch(this.get('tag'))
			{
				case 'input':
				case 'select':
					return 'focus';
					break;
				default:
					return 'mouseover';
					break;
			}
		}
		return this;
	},
	
	getTooltipDisappearEvent: function()
	{
		if($chk(this.disappearEvent))
		{
			return this.disappearEvent;
		}
		else
		{
			switch(this.appearEvent)
			{
				case 'change':
					return 'focus';
					break;
				case 'keydown':
				case 'keypress':
					return 'keyup';
					break;
				case 'mousedown':
				case 'mousemove':
					return 'mouseup';
					break;
				case 'mouseover':
				case 'mouseup':
					return 'mouseout';
					break;
				case 'focus':
				case 'click':
				case 'dblclick':
				case 'select':
				default:
					return 'blur';
					break;
			}
		}
		return this;
	},
	
	getTooltipPosition: function(arrayPosition)
	{
		
		var mySize = (!isNaN(parseInt(this.forceWidth, 10)) && this.forceWidth > 0) ? this.forceWidth : this.getSize().x;
		if(mySize > 40)
		{
			this.tooltip.setStyle('width', mySize + ( this.padding * 2 ) + "px");
		}
		else
		{
			if(Browser.Engine.trident4)
			{
				this.tooltip.setStyle('width', '1px');
			}
			else if(Browser.Engine.trident4)
			{
				this.tooltip.setStyle('width', 'auto');
			}
		
			if(Browser.Engine.trident)
			{
				mySize = this.tooltip.getSize().x + ( this.padding * 5 );
				this.tooltip.setStyle('width', mySize + ( this.padding * 2 ) + "px");
			}
			else
			{
				arrayPosition = 'top leftSide'.split(" ");
			}
		}
		
		this.setTooltipContent(this.tooltipText);
		var target = this.getCoordinates();
		
		// Force the target coordinates for scrolled elements
		var scrollPos = this.getScrollPosition();
		target.left = scrollPos.x;
		target.top = scrollPos.y;
		
		var position = {left: target.left, top: target.top, fxLeft:0, fxTop:0};
		var tooltipPos = this.tooltip.getCoordinates();
	
		for(var i = 0; i < arrayPosition.length; i++)
		{
			switch(arrayPosition[i])
			{
				case 'top':
					position.top = target.top - tooltipPos.height;
					position.fxTop = 0 - tooltipPos.height;
					break;
				case 'middle':
					position.top = ( target.top + Math.round(target.height / 2) ) - Math.round(tooltipPos.height / 2);
					position.fxTop = 0 - tooltipPos.height;
					position.fxTop = 0;
					break;
				case 'bottom':
					position.top = target.top + target.height;
					position.fxTop = tooltipPos.height;
					break;
				case 'leftSide':
					position.left = target.left;
					position.fxLeft = 0;
					break;
				case 'left':
					position.left = target.left - tooltipPos.width;
					position.fxLeft = 0 - tooltipPos.width;
					break;
				case 'center':
					position.left = target.left + Math.round(target.width / 2) - Math.round(tooltipPos.width / 2);
					position.fxLeft = 0 - tooltipPos.width;
					position.fxLeft = 0;
					break;
				case 'right':
					position.left = target.left + target.width;
					position.fxLeft = tooltipPos.width;
					break;
				case 'rightSide':
					position.left = target.left + (target.width - tooltipPos.width);
					position.fxLeft = tooltipPos.width;
					break;				
			}
		}
		position.fxLeft = position.left + position.fxLeft;
		position.fxTop = position.top + position.fxTop;

		return position;
	},
	
	setTooltipContent: function(content)
	{
		if( !$chk(this.tooltip) )
		{
			var element = this;
			return this.createTooltip(function(){ element.setTooltipContent(content); });
		}
		
		if( $chk(this.tooltip.getElement('.content')) )
		{
			this.tooltip.getElement('.content').set('html', content);
		}
		else
		{
			this.tooltip.set('html', content);
		}
		return this;
	},
	
	updateTooltipContent: function(content)
	{
		if( !$chk(this.tooltip) )
		{
			var element = this;
			return this.createTooltip(function(){ element.updateTooltipContent.bind(element)(content); });
		}
		
		this.setTooltipContent(content);
		this.tooltipText = content;
		this.tooltipPosition = this.getTooltipPosition(this.arrayPosition);
		
		this.tooltipFx = new Fx.Morph(this.tooltip, {
			'duration': 500,
			'wait': false,
			'transition': Fx.Transitions.Back.easeOut
		}).start({
			'top': this.tooltipPosition.top,
			'left': this.tooltipPosition.left
		});
		return this;
	},
	
	attachTooltip: function( options )
	{
		options = $chk(options) ? options : new Object();
		this.element = $chk(options.tooltip) ? options.tooltip : 'urbantooltip';
		this.appearEvent = $defined(options.appearEvent) ? options.appearEvent : this.getTooltipAppearEvent();
		this.disappearEvent = $defined(options.disappearEvent) ? options.disappearEvent : this.getTooltipDisappearEvent();
		this.arrayPosition = $chk(options.position) ? options.position.split(" ") : 'top center'.split(" ");
		this.forceWidth = $defined(options.width) ? options.width : true;
		this.padding = $chk(options.padding) ? options.padding : 0;
		this.tooltipText = $chk(options.content) ? options.content : this.getProperty('title');
		this.extraClass = $chk(options.extraClass) ? options.extraClass : false;

		if ( this.appearEvent != false )
		{
			this.getElements('a').addEvent(this.appearEvent.toString(), function (event) {
				new Event(event).stopPropagation();
				this.disableTooltip();
			});
		}

		if ( this.disappearEvent != false )
		{
			this.getElements('a').addEvent(this.disappearEvent.toString(), function (event) {
				new Event(event).stopPropagation();
				this.enableTooltip();
			});
		}

		if( $chk(this.tooltipText) )
		{			
			var item = this;

			this.removeProperty('title')
					.removeEvent(this.appearEvent.toString(), item.showTooltip)
					.removeEvent(this.disappearEvent.toString(), item.hideTooltip);

			if ( this.appearEvent != false ) this.addEvent(this.appearEvent.toString(), item.showTooltip);
			if ( this.disappearEvent != false ) this.addEvent(this.disappearEvent.toString(), item.hideTooltip);
		}
		return this;
	},
	
	removeTooltip: function()
	{
		var item = this;
		this.removeEvent(this.appearEvent.toString(), item.showTooltip)
			.removeEvent(this.disappearEvent.toString(), item.hideTooltip);
		return this;
	}

});