document.tooltip = {
    trigger:        null,
    container:      null,
    timer:          null,
    hideTimer:      null,
    delay:          500,
    requestDone:    false,
    timerDone:      false,


    init: function() {
        this.createStructure();
    },

    triggerOn: function(event, url) {
        if (this.timer) clearTimeout(this.timer);

        this.trigger = event.target;

        this.timerDone = false;
        this.timer = setTimeout(
            function() {
                var tooltip = document.tooltip;

                tooltip.timerDone = true;
                if (tooltip.requestDone) tooltip.show(event.target);
            },
            this.delay
        );

        $.ajax({
            url: url,
            cache: true,
            success: function(request) {
                var tooltip = document.tooltip;

                tooltip.setContent(request);
                tooltip.requestDone = true;
                if (tooltip.timerDone) tooltip.show(event.target);
            }
        });
    },

    triggerOff: function(event) {
        if (this.timer) clearTimeout(this.timer);

        this.timer = null;

        this.hide();
    },

    setContent: function(content) {
        $(this.container).html(content);
    },

    show: function(target) {
        if (this.hideTimer) {
            clearTimeout(this.hideTimer);
            this.hideTimer = null;
        }

        $(this.container).appendTo($(target).offsetParent());

        var trigger = this.combineCoords(
            {
                width: $(target).width(),
                height: $(target).height()
            },
            $(target).position()
        );

        var container = this.combineCoords(
            {
                width: $(this.container).outerWidth(true),
                height: $(this.container).outerHeight(true)
            },
            $(this.container).position()
        );

        var viewport  = this.combineCoords(
            {
                width: $(window).width(),
                height: $(window).height()
            },
            {
                top: $(window).scrollTop(),
                right: 0,
                bottom: 0,
                left: $(window).scrollLeft()
            }
        );

        var hasSpaceLeft    = viewport.left < trigger.left - container.width;
        var hasSpaceRight   = viewport.left + viewport.width > trigger.left + trigger.width + container.width;
        var hasSpaceCenterX = viewport.left < trigger.left + trigger.width / 2 - container.width / 2
                              && viewport.left + viewport.width > trigger.left + trigger.width / 2 + container.width / 2;

        var hasSpaceTop     = viewport.top < trigger.top - container.height;
        var hasSpaceBottom  = viewport.top + viewport.height > trigger.top + trigger.height + container.height;
        var hasSpaceCenterY = viewport.top < trigger.top + trigger.height / 2 - container.height / 2
                              && viewport.top + viewport.height > trigger.top + trigger.height / 2 + container.height / 2;

        var xLeft   = trigger.left - container.width + 'px';
        var xRight  = trigger.left + trigger.width   + 'px';
        var xCenter = trigger.left + trigger.width / 2 - container.width / 2 + 'px';

        var yTop    = trigger.top - container.height + 'px';
        var yBottom = trigger.top + trigger.height   + 'px';
        var yCenter = trigger.top + trigger.height / 2 - container.height / 2 + 'px';

        switch (true) {
            default:
            case hasSpaceCenterX && hasSpaceTop:
                $(this.container).css('left', xCenter);
                $(this.container).css('top',  yTop);
                break;
            case hasSpaceCenterX && hasSpaceBottom:
                $(this.container).css('left', xCenter);
                $(this.container).css('top',  yBottom);
                break;
            case hasSpaceLeft && hasSpaceCenterY:
                $(this.container).css('left', xLeft);
                $(this.container).css('top',  yCenter);
                break;
            case hasSpaceRight && hasSpaceCenterY:
                $(this.container).css('left', xRight);
                $(this.container).css('top',  yCenter);
                break;
            case hasSpaceTop && hasSpaceLeft:
                $(this.container).css('left', xLeft);
                $(this.container).css('top',  yTop);
                break;
            case hasSpaceTop && hasSpaceRight:
                $(this.container).css('left', xRight);
                $(this.container).css('top',  yTop);
                break;
            case hasSpaceBottom && hasSpaceLeft:
                $(this.container).css('left', xLeft);
                $(this.container).css('top',  yBottom);
                break;
            case hasSpaceBottom && hasSpaceRight:
                $(this.container).css('left', xRight);
                $(this.container).css('top',  yBottom);
                break;
        }

        $(this.container).show();
    },

    hide: function() {
        if (this.hideTimer) {
            clearTimeout(this.hideTimer);
            this.hideTimer = null;
        }

        $(this.container).fadeOut(200);
    },

    hideAfter: function(delay) {
        if (this.hideTimer) { return false; }

        this.hideTimer = setTimeout(function() { document.tooltip.hide(); }, delay);
    },

    isVisible: function() {
        return $(this.container).is(':visible');
    },

    createStructure: function() {
        this.container = (elem = $('#tooltip-container')).length == 1
            ? elem
            : $('<div></div>').attr('id', 'tooltip-container')
                              .hide()
                              .appendTo($('body'));

        $(this.container).click(function() {
            document.tooltip.hide();

            return false;
        });
    },

    combineCoords: function(dimensions, offsets) {
        return {
            top:    offsets.top,
            right:  offsets.right,
            bottom: offsets.bottom,
            left:   offsets.left,
            width:  dimensions.width,
            height: dimensions.height
        };
    }
};

$(document).ready(function() {
    document.tooltip.init();
});
