/* An InfoBox is like an info window, but it displays
* under the marker, opens quicker, and has flexible styling.
* @param {GLatLng} latlng Point to place bar at
* @param {Map} map The map on which to display this InfoBox.
* @param {Object} opts Passes configuration options - content,
*   offsetVertical, offsetHorizontal, className, height, width
*/
function InfoBox(opts) {
	var defaults = {
		offsetVertical: -64,
		offsetHorizontal: -16,
		className: "infobox",
		spacing: 10
	};
	// google.maps.OverlayView.call(this);
	opts = $.extend(defaults, opts);

	this.map_				= opts.map;
	this.offsetVertical_	= opts.offsetVertical;
	this.offsetHorizontal_	= opts.offsetHorizontal;
	this.className_			= opts.className;
	this.spacing_			= opts.spacing;
	this.latlng_			= opts.latlng;
	this.id_				= opts.id;
	this.template_			= opts.template;

	// var me = this;
	// this.boundsChangedListener_ =
	// google.maps.event.addListener(this.map_, "bounds_changed", function() {
	// 	return me.panMap.apply(me);
	// });
	
	this.setMap(this.map_);
}

/* InfoBox extends GOverlay class from the Google Maps API
*/
InfoBox.prototype = new google.maps.OverlayView();

/* Creates the DIV representing this InfoBox
*/
InfoBox.prototype.remove = function() {
	if (this.div_) {
		this.div_.remove();
		this.div_ = null;
	}
};

InfoBox.prototype.hide = function() {
	if (this.div_) {
		this.div_.hide();
	}
};

InfoBox.prototype.show = function() {
	if (this.div_) {
		this.div_.show();
		this.panMap();
	}
};

InfoBox.prototype.toggle = function() {
	if (this.div_) {
		if (this.div_.is(":hidden")) {
			this.show();
		} else {
			this.hide();
		}
	}
};

/* Redraw the Bar based on the current projection and zoom level
*/
InfoBox.prototype.draw = function() {
	// Creates the element if it doesn't exist already.
	if (!this.div_) this.createElement();

	// Calculate the DIV coordinates of two opposite corners of our bounds to
	// get the size and position of our Bar
	var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
	if (!pixPosition) return;

	// Now position our DIV based on the DIV coordinates of our bounds
	this.div_.css({
		left: (pixPosition.x + this.offsetHorizontal_) + "px",
		top: (pixPosition.y + this.offsetVertical_) + "px"
	});
};

/* Creates the DIV representing this InfoBox in the floatPane.  If the panes
* object, retrieved by calling getPanes, is null, remove the element from the
* DOM.  If the div exists, but its parent is not the floatPane, move the div
* to the new pane.
* Called from within draw.  Alternatively, this can be called specifically on
* a panes_changed event.
*/
InfoBox.prototype.createElement = function() {
	var pane = $(this.getPanes().floatPane);
	var div = this.div_;
	if (!div) {
		// This does not handle changing panes.  You can set the map to be null and
		// then reset the map to move the div.
		div = this.div_ = $('<div><div class="item"></div></div>');
		div.addClass(this.className_);
		div.css({
			position: "absolute",
			zIndex: 1000
		});
		
		var that = this;
		pane.append(div);
		that.panMap();
		$.getJSON('/api/property/map-data?id='+that.id_, null, function(data, status) {
			$('div',div).html(that.template_.apply(data.api.data.property));
			div.mouseleave(function(e) {
				that.hide();
			});
		});
		
	} else if (div.parent() != pane) {
		// The panes have changed.  Move the div.
		div.remove();
		pane.append(div);
	} else {
		// The panes have not changed, so no need to create or move the div.
	}
};

/* Pan the map to fit the InfoBox.
*/
InfoBox.prototype.panMap = function() {
	// if we go beyond map, pan map
	var projection = this.getProjection();
	var position = projection.fromLatLngToDivPixel(this.latlng_);

	var nePix = new google.maps.Point(position.x + this.offsetHorizontal_ + this.div_.outerWidth() + this.spacing_, position.y + this.offsetVertical_ - this.spacing_);
	var swPix = new google.maps.Point(position.x + this.offsetHorizontal_ - this.spacing_, position.y + this.offsetVertical_ + this.div_.outerHeight() + this.spacing_);

	var ne = projection.fromDivPixelToLatLng(nePix);
	var sw = projection.fromDivPixelToLatLng(swPix);

	var boxBounds = new google.maps.LatLngBounds(sw,ne);

	this.map_.panToBounds(boxBounds);

	// Remove the listener after panning is complete.
	// google.maps.event.removeListener(this.boundsChangedListener_);
	// this.boundsChangedListener_ = null;
};


