/**
 * Logger configuration
 */
if (typeof logger == 'undefined') {
    var logger = log4javascript.getLogger("control");
    var layout = new log4javascript.PatternLayout("[%c] [%-5p] %m");
    var appender = new log4javascript.PopUpAppender(layout);
    log4javascript.setEnabled(false);
    appender.setThreshold(log4javascript.Level.DEBUG);
    logger.addAppender(appender);
} else {
    try {
        throw new Error("logger already installed.");
    } catch(e) {
        logger.trace(e.message + " " + e.fileName + ", " + e.lineNumber);
    }
};

function Tooltip(name) {
    this.name = name;
    this.properties = {
        "maxWidth":300,     //maximum tooltip width
        "top":40,           //default top margin
        "right":50,         //default right margin
        "bottom":30,        //default bottom margin
        "left":30,          //default left margin
        "padding-left":220  //dafault left padding
    };
    this.x = null;
    this.y = null;
    this.xMax = null;
    this.yMax = null;

    this.context = function() {
        var context = document.getElementById("dynamic");
        logger.trace("1. context " + context);
        if (!context) context = document.getElementById("supplementcontent");
        logger.trace("2. context " + context);
        if (!context) context = document.getElementById("bio");
        logger.trace("3. context " + context);
        if (!context) context = document.getElementById("gloss");
        logger.trace("4. context " + context);
        return context;
    }();

    this.getTopCorrection = function(e) {
        var f = 0;
        logger.trace("0. - " + this.context);
        if (e.x && this.context && !window.opera) {
            logger.trace("1. IE context")
            if (this.context.scrollTop > 0 && this.context.id == 'bio') {
                logger.trace("biography filter");
                f = (-1 * this.context.scrollTop);
            } else if (this.context.id == 'supplementcontent') {
                logger.trace("supplement filter " + document.body.scrollTop + " - " + document.documentElement.scrollTop);
                f = (1 * document.body.scrollTop);
            } else if (this.context.id == 'gloss') {
                logger.trace("glossary filter " + this.context.scrollTop + " - " + document.body.scrollTop + " - " + document.documentElement.scrollTop);
                f = (-1 * this.context.scrollTop);
            }
        }
        return f;
    };

    this.getLeftCorrection = function(e) {
        var f = 0;
        if (window.opera) {
            logger.trace("opera filter - " + this.context.id + " - " + this.context.scrollLeft + " - " + document.body.scrollLeft + " - " + document.documentElement.scrollLeft);
        } else if (e.x && this.context) {
            if (this.context.id == 'dynamic') {
                f = (-1 * this.properties["padding-left"]);
            }
        }
        return f;
    };


    this.handleEvent = function(e) {
        var target = Common.getEventTarget(e);
        logger.trace("target: " + target.id);
        logger.trace("[Tooltip.handleEvent] - target: " + target + " event: [" + e + "]");
        this.captureMousePosition(e);

        var tooltip = document.getElementById(target.id + "tt");
        logger.trace("[Tooltip.handleEvent] - x: [" + this.x + "]");
        logger.trace("[Tooltip.handleEvent] - y: [" + this.y + "]");
        logger.trace(typeof(tooltip));

        if (!tooltip) {
            logger.error("[Tooltip.handleEvent] - tooltip not available");
            return;
        }

        this.toggle(tooltip, e);

        with (tooltip.style) {
            if (display == 'block') {
                position = 'absolute';

                var topcorrection = this.getTopCorrection(e);
                logger.trace("topcorrection: [" + topcorrection + "]");
                top = this.y - this.properties["top"] + topcorrection + "px";

                logger.trace("[Tooltip.handleEvent] - context: [" + this.context.id + "][" + this.context.scrollTop + "][" + this.context.scrollLeft + "]");

                var leftcorrection = this.getLeftCorrection(e);
                logger.trace("leftcorrection: [" + leftcorrection + "]");
                left = this.x + this.properties["left"] + leftcorrection + "px";

                width = 'auto';
                height = 'auto';
                var text = (typeof(tooltip.textContent)) != "undefined" ? tooltip.textContent :
                    (typeof(tooltip.innerText)) != "undefined" ? tooltip.innerText : "";

                logger.trace("1. [" + text.length + "][" + tooltip.offsetWidth + "][" + (text.length/tooltip.offsetWidth) + "]");

                var w = 0;
                var h = 0;
                if (tooltip.offsetWidth > this.properties["maxWidth"]) {
                    w = this.properties["maxWidth"];
                } else if ((text.length/tooltip.offsetWidth) > 0.3) {
                    w = this.properties["maxWidth"];
                } else {
                    w = tooltip.offsetWidth;
                }

                width = w + "px";
                logger.trace("2. [" + text.length + "][" + tooltip.offsetWidth + "][" + (text.length/tooltip.offsetWidth) + "]");

                var is = this.x + w + this.properties["left"];
                var tolerance = new Number(is * 1.05).toFixed();
                var max = this.xMax;
                if (tolerance > max) {
                    logger.error( is + " - " + tolerance + " - " + max);
                    left = this.x - w + leftcorrection - this.properties["right"] + "px";
                } else {
                    logger.trace( is + " - " + tolerance + " - " + max);
                }

            }
        }
        logger.trace("left:" + tooltip.style.left + " - top:" + tooltip.style.top);
    };
    this.toggle = function(tooltip, e) {
        with (tooltip.style) {
            if (e.type == 'mouseover') {
                logger.trace("display block");
                display = "block";
            } else {
                logger.trace("display none");
                display = "none";
            }
        }
    };
    this.getEvent = function(e) {
        if (e == undefined) {
            return window.event;
        } else {
            return e;
        }
    };
    this.captureMousePosition = function(e) {
        var event = this.getEvent(e);
//        if (event.x || event.y) {
//            logger.trace("1. mousepos method");
//            this.x = event.x;
//            this.y = event.y + content.scrollTop;
//            this.xMax = document.body.clientWidth + document.body.scrollLeft;
//            this.yMax = document.body.clientHeight + document.body.scrollTop;
//        } else if (event.pageX || event.pageY) {
//            logger.trace("2. mousepos method");
//            this.x = event.pageX;
//            this.y = event.pageY;
//            this.maxX = window.innerWidth + window.pageXOffset;
//            this.yMax = window.innerHeight + window.pageYOffset;
//        } else if (event.clientX || event.clientY) {
//            logger.trace("3. mousepos method");
//            this.x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
//            this.y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
//            this.xMax = document.body.clientWidth + document.body.scrollLeft;
//            this.yMax = document.body.clientHeight + document.body.scrollTop;
//        } else {
//            logger.error("unable to get mouse position");
//        }

        // TODO: this test might be ambigous
        // right now tested with
        // WinXP: IE6/7, Firefox 2/3, Opera 9
        // Ubuntu 8.04: Firefox 2/3
        if (document.layers) {
            this.x = event.pageX;
            this.y = event.pageY;
            this.xMax = window.innerWidth + window.pageXOffset;
            this.yMax = window.innerHeight + window.pageYOffset;
        } else if (document.all && !window.opera) {
            this.x = event.x + (this.context && this.context.scrollLeft > 0 ? this.context.scrollLeft : 0);
            this.y = event.y + (this.context && this.context.scrollTop > 0 ? this.context.scrollTop : 0);
            this.xMax = document.body.clientWidth + (this.context && this.context.scrollLeft > 0 ? this.context.scrollLeft : 0);
            this.yMax = document.body.clientHeight + (this.context && this.context.scrollTop > 0 ? this.context.scrollTop : 0);
        } else if (document.getElementById) {
            this.x = event.pageX;
            this.y = event.pageY;
            this.xMax = window.innerWidth + window.pageXOffset;
            this.yMax = window.innerHeight + window.pageYOffset;
        }
//        var trace = document.getElementById("query");
//        if (trace) {
//            trace.value = "x:" + this.x + " - y:" + this.y;
//            logger.trace("x:" + this.x + " - y:" + this.y);
//        }

    };

};

var Tools = {};

Tools.showProps = function(node) {
    logger.info("node " + node.nodeName + " " + node.nodeType);
    for (var prop in node) {
        if (typeof(node[prop]) != 'function') {
            logger.info(prop + " - " + typeof(node[prop]) + " - " + node[prop]);
        } else {
            logger.info(prop + " - " + typeof(node[prop]));
        }
    }
};
/**
 * add event handler to object
 * @obj - HTML/DOM object
 * @evt - Event; e.g. click, load ...
 * @fn  - Function registered with event.
 */
Tools.addEvent = function(/*Object*/obj, /*Event*/evt, /*Function*/fn) {
    // TODO: cross browser evaluation !!!
    // perhaps better error handling via boolean return value
    if (obj.addEventListener) {
        //logger.trace("addEventListener to " + obj.nodeName);
        obj.addEventListener(evt,fn,false);
    } else if (obj.attachEvent) {
        //logger.trace("attachEvent " + evt + " to " + obj.nodeName);
        obj.attachEvent('on'+evt,fn);
    } else {
        logger.error("unable to add event listener to " + obj.nodeName);
    }
};
/**
 * remove certain event handler from object
 * @obj - HTML/DOM object
 * @evt - Event; e.g. click, load ...
 * @fn  - Function registered with event.
 */
Tools.removeEvent = function(/*Object*/obj, /*Event*/evt, /*Function*/fn) {
    if (obj.removeEventListener) {
        obj.removeEventListener(evt,fn,false);
    } else if (obj.detachEvent) {
        obj.detachEvent('on'+evt,fn);
    } else {
        logger.warn("unable to remove event listener from " + obj.nodeName);
    }
};

function init() {
    logger.info("Init Tooltips");
    var tooltip = new Tooltip("ChemgaPedia");
    var acronyms = DOMUtil.getElementsWithClassName("span", "acronym");

    for (var a = 0; a < acronyms.length; a++) {
        logger.trace("add handler for " + a.id);
        Tools.addEvent(acronyms[a], "mouseover", function(e) {
            tooltip.handleEvent(e);
        });
        Tools.addEvent(acronyms[a], "mouseout", function(e) {
            tooltip.handleEvent(e);
        });
    }
};

Tools.addEvent(window, "load", init);
