/** @author: Ben Gerrissen @ https://github.com/bgerrissen/jQuery-plugins
 *  @license: MIT
 *  @version: 1.0.0 ( major.minor.bugfix )
 *
 */

(function( $ ){

    if ( !$ ) return;

    var defaultConfig = {
        backgroundColor: "black",
        textColor: "white",
        width: "200px",
        gravity: "s",
        trigger: "hover",
        fadeSpeed: 100,
        opacity: .9
    }

    , $doc = $( document )
    , $win = $( window )

    , triggerMap = {
        hover : {show:"mouseover",hide:"mouseout"},
        focus : {show:"focus",hide:"blur"}
    }

    , tooltip
    , tooltipBox
    , tooltipPointer

    , tooltipHtml = "".concat(
        "<div class='tooltip'><div class='box'></div><div class='pointer'></div></div>"
    )

    , tooltipBoxStyle = {
        "border-radius" : "4px",
        "-moz-border-radius" : "4px",
        "-webkit-border-radius" : "4px",
        "-khtml-border-radius" : "4px",
        padding: "5px 10px 6px 10px",
        fontSize: "11px",
        fontFamily: "Verdana, Arial, Sans-Serif",
        lineHeight: "1.5",
        opacity: .9,
        position:"relative"
    }


    , tooltipArrowStyle = {
        border: "6px solid transparent",
        width: "0px",
        height: "0px",
        position: "absolute"
    }

    , TRANSPARENT = "transparent"
    , pointerReset = {

        borderTopColor: TRANSPARENT,
        borderBottomColor: TRANSPARENT,
        borderLeftColor: TRANSPARENT,
        borderRightColor: TRANSPARENT

    }

    , directionMap = {

        s : "south",
        n : "north",
        w : "west",
        e : "east",
        ns : "autoNS",
        we : "autoWE"

    }

    ;

    function autoNS( offset ) {

        return ( offset.top > ( $doc.scrollTop() + ( $win.height() / 2 ) ) ) ? "north" : "south";

    }

    function autoWE( offset ) {

        return ( offset.left > ( $doc.scrollLeft() + ( $win.width() / 2 ) ) ) ? "west" : "east";

    }

    function showTooltip( e ) {

        var el = $( e.currentTarget )
        , offset // set after txt check
        , cfg = e.data.tooltipConfig
        , gravity = cfg.gravity
        , txt = el.attr( "title" );

        if ( !txt ) {

        	return hideTooltip( e );

        }

        el.data( "last-title" , txt );
        el.attr( "title" , "" );

        offset = el.offset();

        tooltip.css({
            opacity: cfg.opacity,
            width: cfg.width
        });

        tooltipBox.css({
            background: cfg.backgroundColor,
            color: cfg.textColor
        });

        tooltip.stop( true )
               .fadeIn( cfg.fadeSpeed )
               .find( ".box" )
               .html( txt );

        if ( gravity == "autoNS" ) {

            gravity = autoNS( offset );

        } else if ( gravity == "autoWE" ) {

            gravity = autoWE( offset );

        }

        setPointer( tooltip.find( ".pointer" ) , gravity , cfg.backgroundColor );

        if ( gravity == "south" ) {

            offset.left = offset.left + ( el.outerWidth() / 2 ) - ( tooltip.outerWidth() / 2 );
            offset.top = offset.top + el.outerHeight();

        } else if ( gravity == "north" ) {

            offset.left = offset.left + ( el.outerWidth() / 2 ) - ( tooltip.outerWidth() / 2 );
            offset.top = offset.top - tooltip.outerHeight();

        } else if ( gravity == "east" ) {

            offset.left = offset.left + el.outerWidth();
            offset.top = offset.top + ( ( el.outerHeight() / 2 ) - ( tooltip.outerHeight() / 2 ) );

        } else if ( gravity == "west" ) {

            offset.left = offset.left - tooltip.outerWidth();
            offset.top = offset.top + ( ( el.outerHeight() / 2 ) - ( tooltip.outerHeight() / 2 ) );

        }

        tooltip.css( offset );

    }

    function hideTooltip( e ) {

        var el = $( e.currentTarget );

        el.attr( "title" , el.data( "last-title" ) );

        tooltip.stop(true).fadeOut( e.data.tooltipConfig.fadeSpeed );

    }

    function setPointer( el , gravity , bgColor ) {

        el[ 0 ].className = "pointer pointer-" + gravity;

        var p
        , h = el.outerHeight()
        , w = el.outerWidth();

        if ( gravity == 'south' ) {

            el.css( $.extend( {} ,pointerReset , {

                top : 0 - ( h / 2 ),
                left: ( ( tooltip.outerWidth() / 2 ) - ( w / 2 ) ),
                borderBottomColor: bgColor

            } ) );

        } else if ( gravity == 'north' ) {

            el.css( $.extend( {} ,pointerReset , {

                top : tooltip.outerHeight() - ( el.outerHeight() / 2 ),
                left: ( ( tooltip.outerWidth() / 2 ) - ( w / 2 ) ),
                borderTopColor: bgColor

            } ) );

        } else if ( gravity == 'west' ) {

            el.css( $.extend( {} ,pointerReset , {

                top: ( tooltip.outerHeight() / 2 ) - ( h / 2 ),
                left: tooltip.outerWidth() - ( w / 2 ),
                borderLeftColor: bgColor

            } ) );

        } else if ( gravity == 'east' ) {

            el.css($.extend( {} ,pointerReset , {

                top: ( tooltip.outerHeight() / 2 ) - ( h / 2 ),
                left: 0 - ( w / 2 ),
                borderRightColor: bgColor

            } ) );

        }

    }

    $.fn.tooltip = function ( config ) {

        config = $.extend( true, {} , defaultConfig , config );
        config.gravity = directionMap[ config.gravity ] || config.gravity;

        if ( !triggerMap[ config.trigger ] ) return;

        if ( !tooltip ) {

            tooltip = $( tooltipHtml ).css({
                zIndex: 99999,
                padding: "5px",
                position: "absolute"
            });

            tooltipBox = tooltip.find( ".box" ).css( tooltipBoxStyle );
            tooltipPointer = tooltip.find( ".pointer" ).css( tooltipArrowStyle );

            tooltip.hide().appendTo( "body" );

        }

        this.live( triggerMap[ config.trigger ].show , {tooltipConfig:config}, showTooltip );
        this.live( triggerMap[ config.trigger ].hide , {tooltipConfig:config}, hideTooltip );

    };

    $.fn.tooltip.defaultConfig = function ( config ) {

        $.extend( defaultConfig , config );

    }

}( jQuery ));
