/**
 * @author dmccuen
 */
var Bubble = Class.create(PBLayeredPanel,{
    pbType: "Bubble",
    initialize: function($super,cfg) {
        $super(cfg.elemId);
        this.id = cfg.elemId||null;
        this.targetId = cfg.targetId||null;
        this.targetElem = $(this.targetId);
        this.posOffset = cfg.posOffset||null;
        this.eventOn = cfg.eventOn||null;
        this.eventOff = cfg.eventOff||null;
        this.callbackOn = cfg.callbackOn||null;
        this.callbackOff = cfg.callbackOff||null;
        this.callbackClose = cfg.callbackClose||null;
        this.offsetX = cfg.offsetX||0;
        this.offsetY = cfg.offsetY||0;
        this.useWindow = cfg.useWindow||null;
        
        if (this.targetElem) {
            if (this.eventOn) {
                if(this.useWindow) {
                    Event.observe(this.useWindow, this.eventOn, this.handleBubbleShow.bindAsEventListener(this), false);                
                } else {
                    Event.observe(this.targetElem, this.eventOn, this.handleBubbleShow.bindAsEventListener(this), false);
                }
            }
            
            if (this.eventOff) {
                if(this.useWindow) {
                    Event.observe(this.useWindow, this.eventOff, this.handleBubbleHide.bindAsEventListener(this), false);                
                } else {
                    Event.observe(this.targetElem, this.eventOff, this.handleBubbleHide.bindAsEventListener(this), false);
                }
            }
        }
        
        // Get Close Link and attach a close bubble handler
        // Note: Close Bubble links always have a class of "closebox"
        var closeLink = $$("#" + this.elemId + " .closebox")
        if (closeLink != "undefined" && closeLink != null && closeLink.length > 0){ 
            closeLink = closeLink[0];
            Event.observe(closeLink, "click", this.handleCloseLink.bindAsEventListener(this), false);
        }
        
        this.setPosition();
    },
    // EVENT HANDLERS
    handleBubbleShow : function(evnt) {
        // only show one bubble at a time!
        if (this.otherBubblesShowing()) {
            return;
        }
        var eltLink = this.getEventLink(evnt);
        var bRet = true;

        if(eltLink && typeof(eltLink.tagName) != "undefined" && eltLink.tagName == "A"){
            bRet = false;
        }

        if(typeof(this.callbackOn) != "function" || this.callbackOn(evnt)){
            this.setPosition();
            Element.show(this.elem);
        }

        return bRet;
    },
    handleBubbleHide : function(evnt) {
        var eltLink = this.getEventLink(evnt);
        var bRet = true;

        if( eltLink && typeof(eltLink.tagName) != "undefined" && eltLink.tagName == "A"){
            bRet = false;
        }

        if(typeof(this.callbackOff) != "function" || this.callbackOff(evnt)){
            Element.hide(this.elem);
        }

        return bRet;
    },
    handleCloseLink : function(evnt) {
        if (typeof(this.callbackClose) != "function" || this.callbackClose()) {
            Element.hide(this.elem);
        }
        return false;
    },
    // PUBLIC METHODS
    show: function() {
        return this.handleBubbleShow(null);
    },
    hide: function() {
        return this.handleBubbleHide(null);
    },
    close: function() {
        return this.handleCloseLink(null);
    },
    // PRIVATE METHODS
    getEventLink: function(evnt) {
        return (evnt && evnt.type == "click") ? Event.findElement(evnt, "A"):null;
    },
    setPosition : function() {
        if (this.elem && !Element.visible(this.elem) && this.targetElem) {
            if (this.posOffset) {
                var o = Element.positionedOffset(this.targetElem);    
            } else {
                var o = Element.cumulativeOffset(this.targetElem);
            }
            var s = this.elem.style;
            var v = s.visibility;
            s.visibility = "hidden";
            Element.show(this.elem);
            s.left = o.left - this.elem.offsetWidth + this.offsetX + "px";
            s.top = o.top + this.offsetY + "px";
            s.visibility = v;
            Element.hide(this.elem);
        }
    },
    otherBubblesShowing: function() {
        var bubbles = jq('.bubbble');
        var isShowing = false;
        bubbles.each(function() {
            if (jq(this).is(':visible')) {
                isShowing = true;
                return false;
            }
        });
        return isShowing;
    }
});

