var UserTooltipManager = {

    selector       : '.user-tooltip',
    contentOptions : {
        url : buildURL('users', 'ajax-card'),
        key : 'id',
        pattern : /.*user\-id\=([0-9]+)/
    },

    init : function() {
        this.applyTooltips();
    },

    applyTooltips : function(selector, options) {
        Ext.each(this.getNodes(selector), function(node) {
            if (typeof Ext.get(node).tooltip != 'object') {
                new UserTooltip(node, options);
            }
        }, this);
    },

    getNodes : function(selector) {
        selector = !Ext.isEmpty(selector) ? selector : this.selector;

        return Ext.query(selector);
    }
};

function UserTooltip (node, options) {

    Ext.apply(this, options, {
        containerClass: 'user-tooltip-container',
        positionClass: {
            top: 't',
            topLeft: 'tl',
            topRight: 'tr',
            bottom: 'b',
            bottomLeft: 'bl',
            bottomRight: 'br'
        },
        limitBox: Ext.getBody(),
        showDelay: 300,
        hideDelay: 300,
        contentOptions: UserTooltipManager.contentOptions
    });

    this.isLoaded     = false;
    this.visible      = false;
    this.node         = Ext.get(node);
    this.node.tooltip = this;
    this.redirectOnAction = !this.node.hasClass('no-redir-tooltip-buttons');

    if (Ext.isEmpty(this.identifier)) {
        if (typeof options != 'undefined' && typeof options.customUserId != 'undefined' && options.customUserId) {
            this.identifier = options.customUserId;
        } else if (this.node.getAttributeNS(null, 'href')) {
            this.identifier = this.node.getAttributeNS(null, 'href').replace(this.contentOptions.pattern, '$1');
        } else {
            this.identifier = this.node.getAttributeNS(null, 'classname').replace(this.contentOptions.pattern, '$1');
        }
    }

    this.node.addListener('mouseover', this.waitShow, this);
    this.node.addListener('mouseover', this.cancelHide, this);

    this.node.addListener('mouseout', this.cancelShow, this);
    this.node.addListener('mouseout', this.waitHide, this);
};

UserTooltip.prototype = {
    containerClass: '',
    container: null,
    positionClass: {},
    currentPositionClass: '',
    limitBox: null,
    showDelay: 1000,
    hideDelay: 1000,
    showingTask: null,
    hidingTask: null,
    isLoaded: false,
    loading: false,
    identifier: null,
    redirOnAction: true,

    getNode : function() {
        /* declare button "send-message" as Lightbox (into tool tip) */
        if (!Ext.isEmpty(Ext.get('send-message-user-' + this.identifier))) {
            Lightbox.assign(Ext.get('send-message-user-' + this.identifier), {}, true);
        }

        /* declare button "introduce" as Lightbox (into tool tip) */
        if (!Ext.isEmpty(Ext.get('introduce-user-' + this.identifier))) {
            Lightbox.assign(Ext.get('introduce-user-' + this.identifier), {}, true);
        }

        /* declare button "note & remind" as Lightbox (into tool tip) */
        if (!Ext.isEmpty(Ext.get('note-remind-user-' + this.identifier))) {
            Lightbox.assign(Ext.get('note-remind-user-' + this.identifier), {}, true);
        }

        /* declare button "invitation" as Lightbox (into tool tip) */
        if (!Ext.isEmpty(Ext.get('invitation-user-' + this.identifier))) {
            Lightbox.assign(Ext.get('invitation-user-' + this.identifier), {}, true);
        }

        return Ext.get(this.node);
    },

    createContainer : function() {
        this.container = Ext.DomHelper.append(Ext.getBody(), {tag: 'div'}, true).hide();

        this.container.addClass(this.containerClass).setX(1).setY(1);

        this.container.addListener('mouseover', this.cancelHide, this);
        this.container.addListener('mouseout', this.waitHide, this);
    },

    getContainer : function() {

        if (null === this.container) {
            this.createContainer();
        }

        return this.container;
    },

    show : function() {
        if (!this.getContainer().isVisible() && null != this.identifier) {
            this.refresh();
            this.getContainer().show(true);
        }
    },

    waitShow : function() {
        if (this.isLoaded == false) {
            this.load();
        }

        this.showingTask = new Ext.util.DelayedTask(this.show, this);
        this.showingTask.delay(this.showDelay);
    },

    cancelShow : function() {
        if (this.showingTask != null) {
            this.showingTask.cancel();
            this.showingTask = null;
        }
    },

    hide : function() {
        this.getContainer().hide(true);
    },

    waitHide : function() {
        this.hidingTask = new Ext.util.DelayedTask(this.hide, this);
        this.hidingTask.delay(this.hideDelay);
    },

    cancelHide : function() {
        if (this.hidingTask != null) {
            this.hidingTask.cancel();
            this.hidingTask = null;
        }
    },

    load : function() {
        if (null != this.identifier && !this.loading && !this.isLoaded) {
            this.loading = true;
            this.getContainer().load({
                url : this.contentOptions.url + this.contentOptions.key + '=' + this.identifier + '&redirect=' + (this.redirectOnAction ? '1' : '0'),
                callback : function() {
                    this.isLoaded = true;
                    this.loading = false;
                    this.refresh();
                },
                scope : this,
                nocache : true
            });
        }
    },

    refresh : function() {

        var node      = this.getNode(),
            container = this.getContainer(),
            nBox = node.getBox(),
            cBox = container.getBox(),
            lBox = this.limitBox.getBox(),
            centerX = nBox.x + parseInt(nBox.width / 2);

        var box = {};

        if (nBox.y - cBox.height > lBox.y) {
            box.y  = nBox.y - cBox.height;
        } else {
            box.y  = nBox.y + nBox.height;
        }

        box.x = centerX - parseInt(cBox.width / 2);

        if (lBox.x >= box.x) {
            box.x  = nBox.x + nBox.width;
        } else if (lBox.x + lBox.width <= box.x + cBox.width) {
            box.x  = nBox.x - cBox.width;
        }

        container.setX(box.x).setY(box.y);
    },

    setIdentifier: function(identifier)
    {
        if (identifier != this.identifier) {
            this.isLoaded = false;
        }

        this.identifier = identifier;

        return this;
    }

};

Ext.onReady(UserTooltipManager.init, UserTooltipManager, { delay: 500 });
