
$(function()
{
	tcsToolTipObj = new Object();
	tipPositions = new Object();
	jQuery.showTailA = function(jElem, color){
	    var i;
	    var startX = -1;
	    var startY = -1;
	    var startWidth = 16;
	    for (i=0; i<8; i++)
	    {
	        var bar = jQuery('<div></div>').css({
	            position: 'absolute',
	            top: startY - i + 'px',
	            left: startX + i + 'px',
	            width: startWidth - i * 2 + 'px',
	            height: '1px',
	            background: color,
	            color: 'black'
	        });
	        jElem.append(bar);
	    }
	}
	jQuery.showTailB = function(jElem, color){
	    var i;
	    var startX = 4;
	    var startY = -1;
	    var startWidth = 16;
	    for (i=0; i<8; i++)
	    {
	        var bar = jQuery('<div></div>').css({
	            position: 'absolute',
	            top: startY - i + 'px',
	            left: startX - i + 'px',
	            width: startWidth - i * 2 + 'px',
	            height: '1px',
	            background: color,
	            color: 'black'
	        });
	        jElem.append(bar);
	    }
	}
	
	
	jQuery.fn.tooltip = function()
	{
	    var thisobj = this;
	    var defaults = {
	        css: {
	            background: '#dfdfdf',
	            border: '1px solid #afafaf',
	            font: 'normal small Trebuchet MS,  Arial',
	            padding: '5px'
	        },
	        content: function() { return 'hello, hello, hello! :)'; },
	        showTail: true,
	        relativeLeft: 0,
	        relativeTop: 0,
	        static: false,
	        tailColor: '#afafaf',
	        transition: null
	    };
	    return {
	        create: function(options) {
	            var optionsExist = (typeof(options) != 'undefined');
	            var rand = Math.ceil(Math.random() * 10000);
	            jQuery.each(thisobj, function() {
	                var jElem = jQuery(this);
	                // CODE NOTE: if an element doesn't have an ID, assign a random ID.  The hash lookup below must use a unique identifier!!!
	                if (jElem[0].id == '')
	                    jElem[0].id = 'tcsToolTipHostElem' + rand;
	                var tip = jQuery('<div></div>').css({
	                    position: 'absolute',
	                    top: jElem.offset().top + jElem.height() + 5 + (optionsExist && typeof options.relativeTop != 'undefined' ? options.relativeTop : defaults.relativeTop) + 'px',
	                    left: jElem.offset().left + jElem.width() - 10 + (optionsExist && typeof options.relativeLeft != 'undefined' ? options.relativeLeft : defaults.relativeLeft) + 'px'
	                }).hide().css(
	                    optionsExist && typeof(options.css) != 'undefined'?
	                    options.css:
	                    defaults.css
	                );
	
	                // add content
	                if (optionsExist && typeof options.content == 'function')
	                {
	                    var content = options.content(tip[0], options.data);
	                    // check if jquery elem
	                    if (typeof content.jquery != 'undefined' || typeof content == 'object' && typeof content.tagName != 'undefined')
	                    {
	                        content.appendTo(tip);
	                    }
	                    else if (typeof content == 'string')
	                        tip.html(content);
	                }
	                else
	                    tip.html(defaults.content());
	
	                tip.addClass('tcsToolTip');
	                tip[0].id = 'tooltip' + rand;
					
					tipPositions[tip[0].id] = new Object();
					if (optionsExist && typeof options.relativeLeft != 'undefined')
					{
						tipPositions[tip[0].id].relativeLeft = options.relativeLeft;	
					}	
					
					if (optionsExist && typeof options.relativeTop != 'undefined')
					{
						tipPositions[tip[0].id].relativeTop = options.relativeTop;	
					}		
					
	                jQuery(
	                    jQuery('form').length == 0?
	                    'body':
	                    'form'
	                ).append(tip);
	
	                if ((optionsExist && options.showTail) || (!(optionsExist) && defaults.showTail))
	                    jQuery.showTailA(tip, (optionsExist && options.tailColor ? options.tailColor : defaults.tailColor));
	
	                var t;
	
	                // if the variable "static" is true in options, do not add a hover handler.  in stead, add a "click to close" handler
	
	                if ((optionsExist && options.static) || (!(optionsExist) && defaults.static))
	                {
	                    var closeMsg = jQuery('<div></div>').text('(click to close)');
	                    if (jQuery.browser.msie || jQuery.browser.safari || jQuery.browser.opera)
	                        closeMsg.css('text-align', 'center');
	                    else
	                        closeMsg.css('text-align', '-moz-center');
	                    closeMsg.css({
	                        font: 'normal italic 7pt  arial, helvetica',
	                        color: (optionsExist && typeof options.css != 'undefined' && typeof options.css.color != 'undefined' ? options.css.color : 'black'),
	                        marginTop: '5px'
	                    });
	
	                    if (optionsExist && (typeof options.showClickToClose == 'undefined' || options.showClickToClose == true)) tip.append(closeMsg);
	                    tip.show();
	
	                }
	                else
	                {
	                    var transitionToApply = (optionsExist && options.transition != null && typeof jQuery.effects != 'undefined' ? options.transition : null);
	                    transitionToApply = (transitionToApply != null && typeof jQuery.effects[transitionToApply] != 'undefined' ? transitionToApply : null);
	                    
	                    var transitionDuration = (optionsExist && options.transitionDuration != null ? options.transitionDuration : 300);
	                    
	                    jElem.hover(
	                        function()
	                        {
	                            clearTimeout(t);
	                            t = setTimeout(function() 
	                            { 
	                                if (transitionToApply != null) 
	                                    tip.show(transitionToApply, {}, transitionDuration); 
	                                else
	                                    tip.show();
	                            }, 200);
	                        },
	                        function() {
	                            clearTimeout(t);
	                            t = setTimeout(function() 
	                            { 
	                                if (transitionToApply != null) 
	                                    tip.hide(transitionToApply, {}, transitionDuration); 
	                                else
	                                    tip.hide(); 
	                            }, 200);
	                        });
	                    tip.hover(
	                        function()
	                        {
	                            clearTimeout(t);
	                        },
	                        function()
	                        {
	                            clearTimeout(t);
	                            t = setTimeout(function() 
	                            { 
	                                if (transitionToApply != null) 
	                                    tip.hide(transitionToApply, {}, transitionDuration); 
	                                else
	                                    tip.hide(); 
	                            }, 200);
	                        });
	                }
	                tcsToolTipObj[jElem[0].id] = tip;
					if (!((optionsExist && options.static) || (!(optionsExist) && defaults.static))) 
					    tip.hide();
					setTimeout(function()
					{
						jElem.tooltip().reposition();
					}, 100);
	            });
	        },
	        get: function() {
	            if (thisobj.length == 1)
				{	
					var retobj = tcsToolTipObj[thisobj[0].id];
	                return (typeof retobj == 'undefined' ? null : jQuery(retobj));			
				}
	            var containerArray = new Array();
	            jQuery.each(thisobj, function() {
	                containerArray.push(jQuery(tcsToolTipObj[thisobj[0].id]));
	            });
	            return containerArray;
	        },
	        reposition: function(options){
	            var relLeft, relTop;
	            jQuery.each(thisobj, function(){
	                var jElem = jQuery(this);
					log.info(typeof this);
	                var tip = jElem.tooltip().get();
	                if (typeof options == 'undefined')
					{
						if (typeof tipPositions[tip[0].id].relativeLeft != 'undefined')
							relLeft = tipPositions[tip[0].id].relativeLeft;
							
						if (typeof tipPositions[tip[0].id].relativeTop != 'undefined')
							relTop = tipPositions[tip[0].id].relativeTop;
						
	                    relLeft = (typeof relLeft == 'undefined' ? 0 : relLeft);
						relTop = (typeof relTop == 'undefined' ? 0 : relTop);	
					}
	                else
	                {
	                    relLeft = (typeof options.relativeLeft == 'undefined' ? 0 : options.relativeLeft);
	                    relTop = (typeof options.relativeTop == 'undefined' ? 0 : options.relativeTop);
	                }
	
	                tip.css({
	                    top: jElem.offset().top + jElem.height() + 5 + relTop + 'px',
	                    left: jElem.offset().left + jElem.width() - 10 + relLeft + 'px'
	                });
	            });
	        }
	    };
	}
});