/**
 * $Id: calloutinterface.js 76074 2009-11-19 20:53:10Z kchiu $
 * $Author: kchiu $
 * $Revision: 76074 $
 * $Name$
 * $Date: 2009-11-19 12:53:10 -0800 (Thu, 19 Nov 2009) $
 *
 * @jsRequire DomUtils
 * @jsRequire interfaces.Interface
 * @jsRequire interfaces.AnchoredInterface
 *
 *
 * @version    $Revision: 76074 $
 * @author     Philip Snyder <philip@pricegrabber.com>
 * @copyright  Copyright &copy; 2006, Philip Snyder, PriceGrabber.com
 * @see        interfaces.Interface
 * @see        interfaces.AnchoredInterface
 */

/**
 * CalloutInterface Constructor / Definition
 *
 * This interface is built on top of the Interface object
 * and is NOT intended to be instantiated directly. See
 * documentation on interfaces.Interface for a complete
 * explanation.
 *
 * @access public
 * @since  v1.1
 * @return CalloutInterface
 */
function CalloutInterface() {
    this.calloutId      = null;
    this.elemId         = null;
    this.anchorId       = null;
    this.calloutPadding = 0;
    // Callout interface implementation
    this.erase             = CalloutInterface_Erase;
    this.draw              = CalloutInterface_Draw;
    this.alignElement      = CalloutInterface_AlignElement;
    // Anchored interface implementation
    this.disableScroll     = false;
    this.getAnchorX        = AnchoredInterface_GetAnchorX;
    this.getAnchorY        = AnchoredInterface_GetAnchorY;
    this.getAnchorZ        = AnchoredInterface_GetAnchorZ;
    this.getAnchorWidth    = AnchoredInterface_GetAnchorWidth;
    this.getAnchorHeight   = AnchoredInterface_GetAnchorHeight;
    this.getElemWidth      = AnchoredInterface_GetElemWidth;
    this.getElemHeight     = AnchoredInterface_GetElemHeight;
    this.getAnchorPosition = AnchoredInterface_GetAnchorPosition;
    this.setAnchor         = AnchoredInterface_SetAnchor;
    this.implement(AnchoredInterface);
    return this;
} // End CalloutInterface

// Setup CalloutInterface prototype chain
CalloutInterface.prototype             = new Interface;
CalloutInterface.prototype.constructor = CalloutInterface;
CalloutInterface.superclass            = Interface.prototype;






/****** BEGIN EDIT SECTION ******/

/**
 * General Settings
 *
 * Defines general settings for the callout interface. These can
 * be overridden by any script after inclusion of this file. 
 *
 * Example:
 *
 *    <script language="JavaScript">
 *    CalloutInterface.settings.images.left.src = 'http://i.pgcdn.com/images/callout/left_arrow.gif';
 *    // Or even...
 *    CalloutInterface.settings.images.left = { src: 'http://i.pgcdn.com/images/callout/left_arrow.gif', height: 20, width: 10 };
 *    </script>
 *
 * Note that 'http://i.pgcdn.com' is included... if you
 * don't include the full path, the url will be relative to your
 * web server -- which in general is wrong except for during
 * development.
 *
 * @access public
 * @since  v1.1
 * @var    CalloutInterface.settings   struct
 */
CalloutInterface.settings = {
    images: {
        left:   { src: util.resourceManager.get('http://i.pgcdn.com/images/balloon/left_arrow.gif'),   height: 23, width: 11 },
        top:    { src: util.resourceManager.get('http://i.pgcdn.com/images/balloon/top_arrow.gif'),    height: 11, width: 23 },
        right:  { src: util.resourceManager.get('http://i.pgcdn.com/images/balloon/right_arrow.gif'),  height: 21, width: 11 },
        bottom: { src: util.resourceManager.get('http://i.pgcdn.com/images/balloon/bottom_arrow.gif'), height: 11, width: 23 }
    }
};

/****** END EDIT SECTION ******/







/**
 * CalloutInterface.erase()
 *
 * "Erases" the callout by removing the dom elements created with CalloutInterface.draw().
 *
 * @access public
 * @since  v0.0.1a
 * @return void
 */
function CalloutInterface_Erase() {
    //window.messageQueue.add( new Message('CalloutInterface_Erase', 'called') );
    var callout = document.getElementById(this.calloutId);
    if (callout) {
        //callout.parentNode.removeChild(callout);
        DomUtils.removeElement(callout);
    }
    callout = null;
    //window.messageQueue.add( new Message('CalloutInterface_Erase', 'finished') );
} // End CalloutInterface_Erase


/**
 * CalloutInterface.draw()
 *
 * "Draws" the actual callout by creating the necessary dom elements and applying them to
 * the object's element.
 *
 * @access public
 * @since  v0.0.1a
 * @return void
 */
function CalloutInterface_Draw() {
    //window.messageQueue.add( new Message('CalloutInterface_Draw', 'called') );
    if (!this.calloutId) this.calloutId = this.id+'_Callout';
    var elem    = document.getElementById(this.elemId);
    if (!elem) throw new Error('Unable to find element: '+this.elemId);
    var anchor  = document.getElementById(this.anchorId);
    if (!anchor) throw new Error('Unable to find anchor element: '+this.anchorId);
    if (elem && anchor) {
        elem.style.padding = '1px';
        elem.style.border  = '1px solid #dadada';
        //elem.style.backgroundColor = '#ffffff';
        var callout = document.getElementById(this.calloutId);
        if (callout && callout.parentNode) DomUtils.removeElement(callout);
        var pos                  = this.getAnchorPosition();
        callout                  = document.createElement('img');
        callout.id               = this.calloutId;
        callout.style.position   = 'absolute';
        callout.style.visibility = 'hidden';
        var body = document.getElementsByTagName('body')[0];
        body.appendChild(callout);
        var imgDetails;
        //alert('Callout interface: '+pos);

        switch (pos) {
            case AnchoredInterface.ALIGN.RIGHT_TOP:
                //if (typeof(writeDebug) == 'function') writeDebug('right_top');
                imgDetails        = CalloutInterface.settings.images.top;
                //window.messageQueue.add( new Message('callout img', 'right_top: '+imgDetails.src) );
                callout.src       = util.resourceManager.get(imgDetails.src);
                callout.height    = imgDetails.height;
                callout.width     = imgDetails.width;
                //callout.style.top = (DomUtils.getElementHeight(elem)+2)+'px';
                //if (DomUtils.browser.isIE() && document.compatMode == 'BackCompat') {
                //    eStyle  = DomUtils.getCurrentStyle(elem);
                //    height  = parseInt(DomUtils.getElementHeight(elem));
                //    callout.style.top = parseInt(height+1)+'px';
                //}
                callout.style.left = this.calloutPadding+'px';
                break;
            case AnchoredInterface.ALIGN.RIGHT_BOTTOM:
                //if (typeof(writeDebug) == 'function') writeDebug('right_bottom');
                imgDetails         = CalloutInterface.settings.images.top;
                //window.messageQueue.add( new Message('callout img', 'right_bottom: '+imgDetails.src) );
                callout.src        = util.resourceManager.get(imgDetails.src);
                callout.height     = imgDetails.height;
                callout.width      = imgDetails.width;
                //callout.style.top  = '-'+(callout.height+(DomUtils.browser.isIE() ? -1 : -1))+'px';
                //callout.style.left = this.calloutPadding+'px';
                break;
            case AnchoredInterface.ALIGN.LEFT_TOP:
                imgDetails         = CalloutInterface.settings.images.top;
                //window.messageQueue.add( new Message('callout img', 'left_top: '+imgDetails.src) );
                callout.src        = util.resourceManager.get(imgDetails.src);
                callout.height     = imgDetails.height;
                callout.width      = imgDetails.width;
                //callout.style.top  = (DomUtils.getElementHeight(elem)+2)+'px';
                //window.messageQueue.add( new Message('CalloutInterface_Draw', 'getting elem width for callout') );
                //callout.style.left = (DomUtils.getElementWidth(elem)-1-callout.width-this.calloutPadding)+'px';
                //window.messageQueue.add( new Message('CalloutInterface_Draw', 'finished elem width for callout') );
                break;
            case AnchoredInterface.ALIGN.LEFT_BOTTOM:
            default:
                //if (typeof(writeDebug) == 'function') writeDebug('left_bottom');
                imgDetails         = CalloutInterface.settings.images.bottom;
                //window.messageQueue.add( new Message('callout img', 'left_bottom: '+imgDetails.src) );
                callout.src        = util.resourceManager.get(imgDetails.src);
                callout.height     = imgDetails.height;
                callout.width      = imgDetails.width;
                //callout.style.top  = '-'+(callout.height+(DomUtils.browser.isIE() ? -1 : -1))+'px';
                //window.messageQueue.add( new Message('CalloutInterface_Draw', 'getting elem width for callout') );
                //callout.style.left = (DomUtils.getElementWidth(elem)-1-callout.width-this.calloutPadding)+'px';
                //callout.style.left = (DomUtils.getElementLeft(elem)-1-callout.width-this.calloutPadding)+'px';
                //window.messageQueue.add( new Message(funcname(this), 'finished elem width for callout') );
                break;
        }

        //elem.appendChild(callout);
        //callout.style.zIndex = parseInt(DomUtils.getZIndex(elem))+1;
        //this.alignElement(pos);
        //CalloutInterface_AlignElement.call(this, pos);
    }
    //window.messageQueue.add( new Message('CalloutInterface_Draw', 'finished') );
} // End CalloutInterface_Draw


/**
 * CalloutInterface.alignElement()
 *
 * Aligns the object's element by adjusting its left & top by the proper calculations (which are done
 * in this function) on the height & width & style of the callout.
 *
 * @access public
 * @since  v0.0.1a
 * @see    AnchoredInterface
 * @param  string    pos      One of the constants defined in AnchoredInterface.ALIGN
 * @return void
 */
function CalloutInterface_AlignElement(pos) {
    //window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'called') );
    pos = pos || this.getAnchorPosition();
    var elem    = document.getElementById(this.elemId);
    if (!elem)    throw new Error('Unable to find element: '+this.elemId);
    var callout = document.getElementById(this.calloutId);
    if (!callout) throw new Error('Unable to find callout element: '+this.calloutId);
    var anchor  = document.getElementById(this.anchorId);
    if (!anchor)  throw new Error('Unable to find anchor element: '+this.anchorId);

    var aTop    = parseInt( DomUtils.getElementTop(anchor) );
    var aLeft   = parseInt( DomUtils.getElementLeft(anchor) );
    var aHeight = parseInt( DomUtils.getElementHeight(anchor) );
    var aWidth  = parseInt( DomUtils.getElementWidth(anchor) );

    var eTop    = parseInt( DomUtils.getElementTop(elem) );
    var eLeft   = parseInt( DomUtils.getElementLeft(elem) );
    var eHeight = parseInt( DomUtils.getElementHeight(elem) );
    var eWidth  = parseInt( DomUtils.getElementWidth(elem) );

    var cHeight = parseInt( DomUtils.getElementHeight(callout) );
    var cWidth  = parseInt( DomUtils.getElementWidth(callout) );
    switch (pos) {
        /**
         * Right Top alignment means:
         *
         *             +--------+
         *             | anchor |
         *             +--------+
         *                 /\
         *    +-----------'  '--+
         *    | elem            |
         *    +-----------------+
         */
        case AnchoredInterface.ALIGN.RIGHT_TOP:
            // Adjust main element's position to accomodate callout element
            elem.style.top       = parseInt( eTop  + cHeight )+'px';
            elem.style.left      = parseInt( eLeft + this.calloutPadding )+'px';
            // Position the callout element
            callout.style.left   = parseInt( aLeft + parseInt( aWidth / 2 ) - parseInt(cWidth / 2) )+'px';
            callout.style.top    = parseInt( aTop  + aHeight + 1)+'px';
            callout.style.zIndex = parseInt(DomUtils.getZIndex(elem))+1;
/*
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'alignment position: right_top') );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.left   = '+DomUtils.getElementLeft(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.top    = '+DomUtils.getElementTop(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.height = '+DomUtils.getElementHeight(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.width  = '+DomUtils.getElementWidth(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.left     = '+DomUtils.getElementLeft(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.top      = '+DomUtils.getElementTop(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.height   = '+DomUtils.getElementHeight(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.width    = '+DomUtils.getElementWidth(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.left  = '+DomUtils.getElementLeft(callout)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.top   = '+DomUtils.getElementTop(callout)) );
*/
            break;
        /**
         * Right Bottom alignment means:
         *
         *    +-----------------+
         *    | elem            |
         *    +-----------,  ,--+
         *                 \/
         *             +--------+
         *             | anchor |
         *             +--------+
         */
        case AnchoredInterface.ALIGN.RIGHT_BOTTOM:
            // Adjust main element's position to accomodate callout element
            elem.style.top       = parseInt( eTop  + cHeight - 1 )+'px';
            elem.style.left      = parseInt( eLeft + this.calloutPadding )+'px';
            // Position the callout element
            callout.style.left   = parseInt( aLeft + parseInt(aWidth/2) - parseInt( cWidth / 2) )+'px';
            callout.style.top    = parseInt( aTop + aHeight )+'px';
            callout.style.zIndex = parseInt( DomUtils.getZIndex(elem) )+1;
/*
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'alignment position: right_bottom') );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.left   = '+DomUtils.getElementLeft(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.top    = '+DomUtils.getElementTop(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.height = '+DomUtils.getElementHeight(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.width  = '+DomUtils.getElementWidth(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.left     = '+DomUtils.getElementLeft(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.top      = '+DomUtils.getElementTop(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.height   = '+DomUtils.getElementHeight(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.width    = '+DomUtils.getElementWidth(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.left  = '+DomUtils.getElementLeft(callout)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.top   = '+DomUtils.getElementTop(callout)) );
*/
            break;
        /**
         * Left Top alignment means:
         *
         *    +--------+
         *    | anchor |
         *    +--------+
         *        /\
         *    +--'  '-----------+
         *    | elem            |
         *    +-----------------+
         */
        case AnchoredInterface.ALIGN.LEFT_TOP:
            // Adjust main element's position to account for the callout
            elem.style.top       = parseInt( eTop + cHeight - 1 )+'px';
            elem.style.left      = parseInt( eLeft - this.calloutPadding )+'px';
            // Position the callout element
            callout.style.left   = parseInt( aLeft + parseInt(aWidth / 2) - parseInt(cWidth / 2) - 1 )+'px';
            callout.style.top    = parseInt( aTop + aHeight )+'px';
            callout.style.zIndex = parseInt( DomUtils.getZIndex(elem) )+1;
/*
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'alignment position: left_top') );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.left   = '+DomUtils.getElementLeft(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.top    = '+DomUtils.getElementTop(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.height = '+DomUtils.getElementHeight(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.width  = '+DomUtils.getElementWidth(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.left     = '+DomUtils.getElementLeft(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.top      = '+DomUtils.getElementTop(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.height   = '+DomUtils.getElementHeight(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.width    = '+DomUtils.getElementWidth(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.left  = '+DomUtils.getElementLeft(callout)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.top   = '+DomUtils.getElementTop(callout)) );
*/
            break;
        /**
         * Left Bottom alignment means:
         *
         *    +-----------------+
         *    | elem            |
         *    +--,  ,-----------+
         *        \/
         *    +--------+
         *    | anchor |
         *    +--------+
         */
        case AnchoredInterface.ALIGN.LEFT_BOTTOM:
        default:
            // Adjust main element's position to account for the callout
            elem.style.top       = parseInt( eTop - cHeight - 2)+'px';
            elem.style.left      = parseInt( eLeft - this.calloutPadding )+'px';
            // Position the callout element
            callout.style.left   = parseInt( aLeft - parseInt( cWidth / 2 ) + parseInt( aWidth / 2 ) - 1 )+'px';
            callout.style.top    = parseInt( aTop - cHeight )+'px';
            callout.style.zIndex = parseInt( DomUtils.getZIndex(elem) )+1;
/*
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'alignment position: left_bottom') );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.left   = '+DomUtils.getElementLeft(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.top    = '+DomUtils.getElementTop(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.height = '+DomUtils.getElementHeight(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'anchor.style.width  = '+DomUtils.getElementWidth(anchor)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.left     = '+DomUtils.getElementLeft(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.top      = '+DomUtils.getElementTop(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.height   = '+DomUtils.getElementHeight(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'elem.style.width    = '+DomUtils.getElementWidth(elem)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.left  = '+DomUtils.getElementLeft(callout)) );
            window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'callout.style.top   = '+DomUtils.getElementTop(callout)) );
*/
            break;
    }
    //window.messageQueue.add( new Message('CalloutInterface_AlignElement', 'finished') );
} // End CalloutInterface_AlignElement

