/*
 * Basic usage:
 *
 * var tooltip = new DGN.ToolTip(trigger, tip, options, persist);
 *
 * trigger  : the element that triggers the display of the tooltip, can be HTMLElement or id
 * tip      : the tip to display, can be a message string or a HTMLElement
 * options  : additional options, see below
 * persist  : tooltip behaviour:
 *            0 = mouseover
 *            1 = click
 *            2 = hybrid, keep open on click
 *
 * Example usage:
 *
 * (HTML)
 *
 * <a id="roll-over-link" href="#id-of-tooltip" />display tool-tip</a>
 *
 * <div id="id-of-tooltip" style="display:none;">
 *   tool-tip text
 * </div>
 *
 * (JavaScript)
 *
 * var elem     = $('roll-over-link');
 * var relative = new DGN.ToolTip(
 *    elem,
 *    $(elem.readAttribute('href').substr(1)),
 *    {
 *        top: -80,
 *        left: 0,              // default
 *        relativeto: elem,     // default (defaults to trigger)
 *        width: '480px'
 *        }
 *    );
 *
 *
 * Options:
 *
 *  classnames
 *  top
 *  left
 *  width
 *  height
 *  relativeto
 *
 */

if (!DGN) { var DGN = { }; }

DGN.ToolTip = Class.create({
    initialize: function(trigger, tip, options, pn_persist) {
        // set the trigger
        if (trigger) {
            this.trigger = $(trigger);
        }

        // setup the tip itself
        if (typeof(tip) == 'string') {
            this.tip = new Element('div').update(tip);
            if (!this.trigger) {
                throw "Trigger not defined for non-pre-existing tool-tip";
            }
            this.trigger.insert({after: this.tip});
        } else {
            this.tip = tip;
        }

        // set options
        this.options            = options || { };
        this.options.classnames = this.options.classname || 'tooltip tip';
        this.options.top        = parseInt(this.tip.style.top || this.options.top || 0);
        this.options.left       = parseInt(this.tip.style.left || this.options.left || 0);
        this.options.width      = this.options.width || (this.tip.getWidth() + 'px');
        this.options.height     = this.options.height || 'auto';
        this.options.relativeto = $(this.options.relativeto || this.trigger);
        if (this.options.relativeto) {
            this.options.relativeto.makePositioned();
        }

        this.tip.addClassName(this.options.classnames);
        this.tip.absolutize();

        // determine starting state
        this.ob_visible = this.tip.visible();
        this.ob_persist = this.ob_visible;

        // set persistence behaviour
        if (pn_persist === undefined) {
            pn_persist = 0;
        }
        this.on_persisttype = pn_persist;

        if (pn_persist == 0) {
            this.hide();
        }
        if (this.trigger) {
            this.attachTo(this.trigger, pn_persist);
        }
    },

    attachTo: function(trigger, pn_persist) {
        trigger = $(trigger);
        if (!this.options.relativeto) {
            trigger.makePositioned();
        }
        if (pn_persist === undefined) {
            pn_persist = this.on_persisttype;
        }
        if (pn_persist == 1 || pn_persist == 2) {
            trigger.observe('click', this.onClick.bindAsEventListener(this));
        }
        if (pn_persist == 0 || pn_persist == 2) {
            trigger.observe('mouseover', this.onMouseOver.bindAsEventListener(this));
            trigger.observe('mouseout', this.onMouseOut.bindAsEventListener(this));
        }
    },

    show: function() {
        if (this.ob_visible) {
            return;
        }
        this.ob_visible = true;

        var relativeto        = this.options.relativeto || this.trigger;
        var position          = relativeto.positionedOffset();
        position.top         += this.options.top;
        position.left        += this.options.left;
        this.tip.style.top    = position.top + 'px';
        this.tip.style.left   = position.left + 'px';
        this.tip.style.width  = this.options.width;
        this.tip.style.height = this.options.height;
        this.tip.style.zIndex = 90;

        if (!this.ob_persist) {
            this.tip.removeClassName('persist');
        }
        this.tip.show();
    },

    onClick: function(e) {
        this.trigger = e.element();
        this.show();
        this.ob_persist = true;
        this.tip.addClassName('persist');
    },

    onMouseOver: function(e) {
        this.trigger = e.element();
        this.show();
    },

    hide: function() {
        this.tip.hide();
        this.ob_visible = false;
        this.ob_persist = false;
        this.tip.removeClassName('persist');
    },

    onMouseOut: function(e) {
        this.trigger = e.element();
        if (this.ob_visible && !this.ob_persist) {
            this.hide();
        }
    }

});

