/**
 * @name WithHoverMarker
 * @version 0.1
 * @author Pierrick Caillon
 * @copyright (c) 2009 In Cité Solution
 * @fileoverview
 *     <p>This library extends the Google Maps API's standard GMarker class or derivative
 *         with the ability to support markers with custom hover tooltip</p>
 */

/**
 * @name WithHoverMarkerOptions
 * @class This class extends <code>GMarkerOptions</code> or other depending on inheritance. 
 *     Instances of this class are used in the <code>opt_opts</code> argument to the
 *     constructor of the WithHoverMarker class.
 * @property {String} [title] Label text to place in the overlay div.
 * @property {String} [hoverClass] CSS class to use for the overlay div
 *     (default "WithHoverMarker_hoverLabel").
 * @property {GSize} [hoverOffset] Label offset, the x- and y-distance
 *     between the marker's latlng and the anchor of the element
 *     (default (0,0)).
 * @property {GSize} [hoverAnchor] Label anchor position, the x- and y-percent
 *     of the label size where the offset anchor is located, from top-left corner
 *     (default (50,100)).
 * @property {Function} [hoverBuilder] Function to create the overlay DOM object
 *     shown on hover (Default to a simple div creator with the text inside).
 */

/**
 * Obtains the constructor for marker with floating over tooltip.
 * @param {Function} baseMarker The constructor of the base marker.
 * @param {String} baseClassName The marker base class name as text.
 * @return {Function} The constructor for the customized marker.
 */
function getHoverMarker(baseMarker, baseClassName)
{
	if (getHoverMarker.classes[baseClassName] != null)
		return getHoverMarker.classes[baseClassName];
	var constructor = function(latlng, opt_opts)
	{
		if (opt_opts == null)
			opt_opts = {};
		this.hm_opts = opt_opts;
		this.hoverText_ = opt_opts.title || "";
		this.hoverClass_ = opt_opts.hoverClass || "WithHoverMarker_hoverLabel";
		this.hoverOffset_ = opt_opts.hoverOffset || new GSize(0, 0);
		this.hoverAnchor_ = opt_opts.hoverAnchor || new GSize(50, 100);
		this.hoverBuilder_ = opt_opts.hoverBuilder || function()
		{
			var description = {
				'tag': 'div',
				'properties': {
					'className': this.hoverClass_
				},
				'children': [
					{
						'tag': '',
						'value': this.hoverText_
					}
				]
			};
			return ics_flexdirectory_createElement(description);
		};
		this.hoverActivated_ = true;
		baseMarker.apply(this, [ latlng, opt_opts ]);
	};
	constructor.prototype = {};
	var base = new baseMarker(new GLatLng(0, 0), {});
	for (var name in baseMarker.prototype)
		constructor.prototype[name] = base[name];
	base = null;
	// TODO: Utiliser une technique ne se basant pas sur la dupplication.
	constructor.prototype.initialize = function (map) 
	{
		baseMarker.prototype.initialize.apply(this, arguments);
		this.map_ = map;
		var pane = map.getPane(G_MAP_MARKER_PANE);
		if (!this.hoverDivFake_)
		{
			this.hoverDivFake_ = this.hoverBuilder_();
			pane.parentNode.insertBefore(this.hoverDivFake_, pane.parentNode.firstChild);
			//pane.parentNode.appendChild(this.hoverDivFake_);
			//this.hoverDivFake_.style.visibility = 'hidden';
			this.hoverDivFake_.style.display = 'none';
			this.hoverDivFake_.style.position = 'relative';
			this.hoverDivFake_.style.zIndex = -1;
			this.hoverDivFake_.style.paddingTop = 0;
			this.hoverDivFake_.style.paddingRight = 0;
			this.hoverDivFake_.style.paddingBottom = 0;
			this.hoverDivFake_.style.paddingLeft = 0;
			this.hoverDivFake_.style.borderTop = 'none';
			this.hoverDivFake_.style.borderRight = 'none';
			this.hoverDivFake_.style.borderBottom = 'none';
			this.hoverDivFake_.style.borderLeft = 'none';
		}
		this.hoverDiv_ = this.hoverBuilder_();
		pane.appendChild(this.hoverDiv_);
		this.hoverDiv_.style.display = 'none';
		this.hoverDiv_.style.position = 'absolute';
		GEvent.addListener(this, "mouseover", GEvent.callback(this, this.showHover_));
		GEvent.addListener(this, "mouseout", GEvent.callback(this, this.hideHover_));
	};
	constructor.prototype.redraw = function(force)
	{
		baseMarker.prototype.redraw.apply(this, arguments);
		this.redrawHover_();
	};
	constructor.prototype.redrawHover_ = function()
	{
		var p = this.map_.fromLatLngToDivPixel(this.getLatLng());
		var z = GOverlay.getZIndex(this.getLatLng().lat());
		this.hoverDivFake_.style.display = 'block';
		if (!this.hovered) this.hoverDiv_.style.display = 'block';
		var fwidth = (this.hoverDivFake_.clientWidth ? this.hoverDivFake_.clientWidth : this.hoverDivFake_.offsetWidth) + 2;
		var fheight = (this.hoverDivFake_.clientHeight ? this.hoverDivFake_.clientHeight : this.hoverDivFake_.offsetHeight);
		this.hoverDiv_.style.width = fwidth + "px";
		this.hoverDiv_.style.height = fheight + "px";
		var width = (this.hoverDiv_.clientWidth ? this.hoverDiv_.clientWidth : this.hoverDiv_.offsetWidth);
		var height = (this.hoverDiv_.clientHeight ? this.hoverDiv_.clientHeight : this.hoverDiv_.offsetHeight);
		if (!this.hovered) this.hoverDiv_.style.display = 'none';
		this.hoverDivFake_.style.display = 'none';
		this.hoverDiv_.style.left = (p.x - ((this.hoverAnchor_.width * width) / 100) + this.hoverOffset_.width) + "px";
		this.hoverDiv_.style.top = (p.y - ((this.hoverAnchor_.height * height) / 100) + this.hoverOffset_.height) + "px";
		this.hoverDiv_.style.zIndex = z;
	};
	constructor.prototype.remove = function()
	{
		this.clearChildren(this.hoverDiv_);
		if (this.hoverDiv_.parentNode != null)
			this.hoverDiv_.parentNode.removeChild(this.hoverDiv_);
		this.hoverDiv_ = null;
		baseMarker.prototype.remove.apply(this, arguments);
	};
	constructor.prototype.clearChildren = function(element)
	{
		while (element.firstChild != null)
		{
			if (element.firstChild.childNodes != null)
				this.clearChildren(element.firstChild);
			element.removeChild(element.firstChild);
		}
	};
	constructor.prototype.copy = function()
	{
		var newMarker = baseMarker.prototype.copy.apply(this);
		for (var name in constructor.prototype)
			newMarker[name] = constructor.prototype[name];
		newMarker.hoverText_ = this.hoverText_;
		newMarker.hoverClass_ = this.hoverClass_;
		newMarker.hoverOffset_ = this.hoverOffset_;
		newMarker.hoverActivated_ = this.hoverActivated_;
		return newMarker;
	};
	constructor.prototype.showHover_ = function()
	{
		this.hovered = true;
		if (this.hoverDiv_ != null)
			this.hoverDiv_.style.display = 'block';
	};
	constructor.prototype.hideHover_ = function()
	{
		if (this.hoverDiv_ != null)
			this.hoverDiv_.style.display = 'none';
		this.hovered = false;
	};
	getHoverMarker.classes[baseClassName] = constructor;
	return constructor;
}
getHoverMarker.classes = {};


