/*
Copyright 2007 GroundWork Open Source, Inc. ("GroundWork")
All rights reserved. This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License version 2 as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License along with this program;
if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

dojo.provide("guava.core.Tooltip");

dojo.require("dojo.html");
dojo.require("dojo.html.*");
dojo.require("dojo.event.*");

/*

Provides replacement tooltip functionality.  Streamlined, meant to only show one tooltip at a time

*/

guava.core.Tooltip = {
    offsetx : 12,
    offsety : 8,

    newelement : function(newid) {
	if (document.createElement)
	{
	    var el = document.createElement('div');
	    el.id = newid;
	    with(el.style)
	    {
		display = 'none';
		position = 'absolute';
	    }
	    el.innerHTML = '&nbsp;';
	    el.style.zIndex = 9000;	// arbitrary but high
	    document.body.appendChild(el);

    /*@cc_on
      @if (@_jscript)
	// This code is seen by IE but not by other browsers.
	    var shim = document.createElement('iframe');
	    shim.style.position = 'absolute';
	    shim.style.top = "0px";
	    shim.style.left = "0px";
	    shim.style.width = "1px";
	    shim.style.height = "1px";
	    shim.style.zIndex = el.style.zIndex - 1;
	    shim.style.display = 'none';
	    document.body.appendChild(shim);
	    el.shim = shim;
      @else*/
	// This code is seen by all browsers except IE.
    /*@end
      @*/
	}
    },

    placeOnScreenPoint : function(node, desiredX, desiredY, padding, hasScroll) {
	if (dojo.lang.isArray(desiredX)) {
	    hasScroll = padding;
	    padding = desiredY;
	    desiredY = desiredX[1];
	    desiredX = desiredX[0];
	}
	// console.log("Desired x %d and desired y %d", desiredX, desiredY);

	if (!isNaN(padding)) {
	    padding = [Number(padding), Number(padding)];
	} else if (!dojo.lang.isArray(padding)) {
	    padding = [0, 0];
	}

	var scroll = dojo.html.getScrollOffset();
	var view = dojo.html.getViewportSize();
	// var doc = dojo.html

	node = dojo.byId(node);
	var oldDisplay = node.style.display;
	// node.style.display="";
	var w = dojo.html.getInnerWidth(node);
	var h = dojo.html.getInnerHeight(node);

	// var w = 140;
	// var h = 50;

	// console.log("View is %o",view);
	// console.log("Scrollx %d and scrolly %d",scroll.x,scroll.y);
	// console.log("HasScroll is %s",hasScroll);

	var x = -1, y = -1;

	// dojo.debug((desiredX+padding[0]) + w, "<=", view.width, "&&", (desiredY+padding[1]) + h, "<=", view.height);
	// console.log("desiredX %d + padding[0] %d <= view.width %d && desiredY %d +padding[1] %d + h %d <= view.height %d   %d",desiredX,padding[0],view.width,desiredY,padding[1],h,view.height);
	if ((desiredX+padding[0]) + w <= view.width && (desiredY+padding[1]) + h <= view.height ) { // TL
	    x = (desiredX+padding[0]);
	    y = (desiredY+padding[1]);
	    // dojo.debug("TL", x, y);
	    // console.log("TL:  x value %d, y value %d",x,y);
	}


	// dojo.debug((desiredX-padding[0]), "<=", view.width, "&&", (desiredY+padding[1]) + h, "<=", view.height);
	if ((x < 0 || y < 0) && (desiredX-padding[0]) <= view.width && (desiredY+padding[1]) + h <= view.height ) { // TR
	    x = (desiredX-padding[0]) - w;
	    y = (desiredY+padding[1]);
	    // dojo.debug("TR", x, y);
	    // console.log("TR:  x value %d, y value %d",x,y);
	}

	// dojo.debug((desiredX+padding[0]) + w, "<=", view.width, "&&", (desiredY-padding[1]), "<=", view.height);
	if ((x < 0 || y < 0) && (desiredX+padding[0]) + w <= view.width && (desiredY-padding[1]) <= view.height ) { // BL
	    x = (desiredX+padding[0]);
	    y = (desiredY-padding[1]) - h;
	    // dojo.debug("BL", x, y);
	    // console.log("BL:  x value %d, y value %d",x,y);
	}

	// dojo.debug((desiredX-padding[0]), "<=", view.width, "&&", (desiredY-padding[1]), "<=", view.height);
	if ((x < 0 || y < 0) && (desiredX-padding[0]) <= view.width && (desiredY-padding[1]) <= view.height ) { // BR
	    x = (desiredX-padding[0]) - w;
	    y = (desiredY-padding[1]) - h;
	    // dojo.debug("BR", x, y);
	    // console.log("BR:  x value %d, y value %d",x,y);
	}

	return this.placeOnScreenLogged(node, x, y, padding, false);

    // //	node.style.display=oldDisplay;
    //
    // 	if (hasScroll) {
    // 		desiredX -= scroll.x;
    // 		desiredY -= scroll.y;
    // 		// console.log("Scrollx %d and scrolly %d",scroll.x,scroll.y);
    // 	}
    //
    //
    // 	if (x < 0 || y < 0 || (x + w > view.width) || (y + h > view.height)) {
    // 		return dojo.html.placeOnScreen(node, desiredX, desiredY, padding, hasScroll);
    // 	}
    //
    // 	x += scroll.x;
    // 	y += scroll.y;
    //
    // 	node.style.left = x + "px";
    // 	node.style.top = y + "px";
    //
    // 	var ret = [x, y];
    // 	ret.x = x;
    // 	ret.y = y;
    // 	return ret;
    },

    /*@cc_on
      @if (@_jscript)
	// This code is seen by IE but not by other browsers.
    positionShim : function (guava_tooltip) {
	var shim = guava_tooltip.shim;
	shim.style.top = guava_tooltip.offsetTop + "px";
	shim.style.left = guava_tooltip.offsetLeft + "px";
	shim.style.width = guava_tooltip.offsetWidth + "px";
	shim.style.height = guava_tooltip.offsetHeight + "px";
    },
      @else*/
	// This code is seen by all browsers except IE.
    /*@end
      @*/

    getmouseposition : function(e) {
	e = dojo.event.browser.fixEvent(e);
	if (document.getElementById)
	{
	    mypagex = dojo.html.getScrollLeft();
	    mypagey = dojo.html.getScrollTop();
	    //mousex =  e.clientX;
	    //mousey = e.clientY;
	    mousex = e.pageX;
	    mousey = e.pageY;
	    // console.log("Mousex %d mousey %d", mousex,mousey);
	    var guava_tooltip = document.getElementById('guava_tooltip');

	    // Let's use Dojo!
	    //function(node, desiredX, desiredY, padding, hasScroll)
	    guava.core.Tooltip.placeOnScreenPoint(guava_tooltip, mousex, mousey, [10,10], true);

    /*@cc_on
      @if (@_jscript)
	// This code is seen by IE but not by other browsers.
	    guava.core.Tooltip.positionShim(guava_tooltip);
      @else*/
	// This code is seen by all browsers except IE.
    /*@end
      @*/

	/*
	    if (mousex > (dojo.html.getViewportWidth() - 140)) {
		guava_tooltip.style.left = null;
		guava_tooltip.style.right = (dojo.html.getViewportWidth() - (mousex - mypagex)) + 'px';
	    } else {
		guava_tooltip.style.left = (mousex+guava.core.Tooltip.offsetx-mypagex) + 'px';
		guava_tooltip.style.right = null;
	    }

	    if (mousey > (dojo.html.getViewportHeight() - 50)) {
		guava_tooltip.style.top = null;
		guava_tooltip.style.bottom = (dojo.html.getViewportHeight() - (mousey - mypagey)) + 'px';
	    } else {
		guava_tooltip.style.bottom = null;
		guava_tooltip.style.top = (mousey+guava.core.Tooltip.offsety - mypagey) + 'px';
	    }
	*/
	}
    },

    placeOnScreenLogged : function (node, desiredX, desiredY, padding, hasScroll, corners, tryOnly) {
	// TODO: make this function have variable call sigs
	//  kes(node, ptArray, cornerArray, padding, hasScroll)
	//  kes(node, ptX, ptY, cornerA, cornerB, cornerC, paddingArray, hasScroll)
	if (desiredX instanceof Array || typeof desiredX == "array") {
	    tryOnly = corners;
	    corners = hasScroll;
	    hasScroll = padding;
	    padding = desiredY;
	    desiredY = desiredX[1];
	    desiredX = desiredX[0];
	}
	if (corners instanceof String || typeof corners == "string") {
	    corners = corners.split(",");
	}
	if (!isNaN(padding)) {
	    padding = [Number(padding), Number(padding)];
	} else if (!(padding instanceof Array || typeof padding == "array")) {
	    padding = [0, 0];
	}
	var scroll = dojo.html.getScroll().offset;
	var view = dojo.html.getViewport();
	node = dojo.byId(node);
	var oldDisplay = node.style.display;
	node.style.display="";
	var bb = dojo.html.getBorderBox(node);
	var w = bb.width;
	var h = bb.height;
	node.style.display=oldDisplay;
	if (!(corners instanceof Array || typeof corners == "array")) {
	    corners = ['TL'];
	}
	var bestx, besty, bestDistance = Infinity, bestCorner;
	for (var cidex=0; cidex<corners.length; ++cidex) {
	    var corner = corners[cidex];
	    var match = true;
	    var tryX = desiredX - (corner.charAt(1)=='L' ? 0 : w) + padding[0]*(corner.charAt(1)=='L' ? 1 : -1);
	    var tryY = desiredY - (corner.charAt(0)=='T' ? 0 : h) + padding[1]*(corner.charAt(0)=='T' ? 1 : -1);
	    // console.log("placeOnScreenLogged: TryX: %d; TryY: %d",tryX,tryY);
	    if (hasScroll) {
		tryX -= scroll.x;
		tryY -= scroll.y;
	    }
	    if (tryX < 0) {
		tryX = 0;
		match = false;
	    }
	    if (tryY < 0) {
		tryY = 0;
		match = false;
	    }
	    var x = tryX + w;
	    if (x > view.width) {
		x = view.width - w;
		match = false;
	    } else {
		x = tryX;
	    }
	    x = Math.max(padding[0], x) + scroll.x;
	    var y = tryY + h;
	    if (y > view.height) {
		y = view.height - h;
		match = false;
	    } else {
		y = tryY;
	    }
	    // y = Math.max(padding[1], y) + scroll.y;
	    y = Math.max(padding[1], y);
	    // console.log("placeOnScreenLogged: x: %d; y: %d",x,y);

	    if (match) { // perfect match, return now
		bestx = x;
		besty = y;
		bestDistance = 0;
		bestCorner = corner;
		break;
	    } else {
		// not perfect, find out whether it is better than the saved one
		var dist = Math.pow(x-tryX-scroll.x,2)+Math.pow(y-tryY-scroll.y,2);
		if (bestDistance > dist) {
		    bestDistance = dist;
		    bestx = x;
		    besty = y;
		    bestCorner = corner;
		}
	    }
	}
	// console.log("placeOnScreenLogged: final x: %d; final y: %d",bestx,besty);
	if (!tryOnly) {
	    node.style.left = bestx + "px";
	    node.style.top = besty + "px";
	}
	return { left: bestx, top: besty, x: bestx, y: besty, dist: bestDistance, corner:  bestCorner};  //  object
    },

    // Possible future extension:  make the background color an additional option.
    tooltip : function(tip, /* optional */ tipwidth) {
	tipwidth = tipwidth || 150;
	if (!document.getElementById('guava_tooltip')) guava.core.Tooltip.newelement('guava_tooltip');
	var guava_tooltip = document.getElementById('guava_tooltip');
	guava_tooltip.innerHTML = tip;
	guava_tooltip.style.width = tipwidth + 'px';
	guava_tooltip.style.paddingLeft = '0.5em';
	guava_tooltip.style.paddingRight = '0.5em';
	guava_tooltip.style.lineHeight = 'normal';
	guava_tooltip.style.display = 'block';
	guava_tooltip.style.borderColor = '#000000';
	guava_tooltip.style.backgroundColor = '#FFE5CC';

    /*@cc_on
      @if (@_jscript)
	// This code is seen by IE but not by other browsers.
	guava.core.Tooltip.positionShim(guava_tooltip);
	var shim = guava_tooltip.shim;
	shim.style.display = 'block';
      @else*/
	// This code is seen by all browsers except IE.
    /*@end
      @*/

	document.onmousemove = guava.core.Tooltip.getmouseposition;
    },

    exit : function() {
	var guava_tooltip = document.getElementById('guava_tooltip');

    /*@cc_on
      @if (@_jscript)
	// This code is seen by IE but not by other browsers.
	var shim = guava_tooltip.shim;
	shim.style.top = "0px";
	shim.style.left = "0px";
	shim.style.width = "1px";
	shim.style.height = "1px";
	shim.style.display = 'none';
      @else*/
	// This code is seen by all browsers except IE.
    /*@end
      @*/

	guava_tooltip.style.display = 'none';
	document.onmousemove = null;
    }
}
