function InfoBox(opts) {
    //this.map_ = null; //only used for panning, which is disabled at the moment (details below)
    this.div_ = null;
    this.marker_ = null;
	this.content_ = null;
	this.title_ = null;

    this.open = function (marker, map) {
        //this.map_ = map; //only used for panning, which is disabled at the moment (details below)
        this.marker_ = marker;
        this.setMap(map);
    }
	
	this.setContent = function (content){
		this.content_ = content;
	}
	
	this.setTitle = function (title){
		this.title_ = title;
	}
}

InfoBox.prototype = new google.maps.OverlayView(); //extends GOverlay class from the Google Maps API
InfoBox.prototype.onAdd = function () {
    var div = document.createElement('div');
    div.className = 'infobox';
    var contentDiv = document.createElement('div');
    contentDiv.className = 'contentArea';
    contentDiv.innerHTML = this.content_;
    var titleDiv = document.createElement('div');
    titleDiv.className = 'titleBar';
    titleDiv.innerHTML = this.title_;
	var closeBtn = document.createElement('div');
    closeBtn.className = 'closeBtn';
	google.maps.event.addDomListener(closeBtn, 'click', removeInfoBox(this));
	div.appendChild(closeBtn);
    div.appendChild(titleDiv);
    div.appendChild(contentDiv);

    this.div_ = div;

    var panes = this.getPanes();
    panes.floatPane.appendChild(div);
	
	function removeInfoBox(infobox) {
		return function() {
			infobox.setMap(null);
		};
	}
}
InfoBox.prototype.draw = function () {
    var overlayProjection = this.getProjection();
    var spot = overlayProjection.fromLatLngToDivPixel(this.marker_.getPosition());
    var div = this.div_;
    div.style.left = spot.x-24 + 'px';
    div.style.top = spot.y-35 + 'px';
	//this.panMap(); //see note below
}
InfoBox.prototype.onRemove = function () {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
}

//not using this at the moment so the user must scroll the map as necessary to see the info wndow
//the problem is that we are loading images into the infowindow and so we don't know the height and
//width of the infowindow at the time this pan function gets called, so we may pan incorrectly
//TODO: we could consider using some onload event for the images and panning after (getting complex)
InfoBox.prototype.panMap = function() {
	var map = this.map_;
	var bounds = map.getBounds();
	if (!bounds) return;

	// The position of the infowindow
	var position = this.marker_.getPosition(); //this is slightly off because we move the window around to overlap with the marker

	// The dimension of the infowindow
	var iwWidth = this.div_.offsetWidth;
	var iwHeight = this.div_.offsetHeight;

	// The offset position of the infowindow
	var iwOffsetX = 24; //this.offsetHorizontal_;
	var iwOffsetY = 35; //this.offsetVertical_;

	// Padding on the infowindow
	var padX = 18; //40;
	var padY = 14; //40;

	// The degrees per pixel
	var mapDiv = map.getDiv();
	var mapWidth = mapDiv.offsetWidth;
	var mapHeight = mapDiv.offsetHeight;
	var boundsSpan = bounds.toSpan();
	var longSpan = boundsSpan.lng();
	var latSpan = boundsSpan.lat();
	var degPixelX = longSpan / mapWidth;
	var degPixelY = latSpan / mapHeight;

	// The bounds of the map
	var mapWestLng = bounds.getSouthWest().lng();
	var mapEastLng = bounds.getNorthEast().lng();
	var mapNorthLat = bounds.getNorthEast().lat();
	var mapSouthLat = bounds.getSouthWest().lat();

	// The bounds of the infowindow
	var iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX;
	var iwEastLng = position.lng() + (iwOffsetX + iwWidth + padX) * degPixelX;
	var iwNorthLat = position.lat() - (iwOffsetY - padY) * degPixelY;
	var iwSouthLat = position.lat() - (iwOffsetY + iwHeight + padY) * degPixelY;

	// calculate center shift
	var shiftLng =
		(iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) +
		(iwEastLng > mapEastLng ? mapEastLng - iwEastLng : 0);
	var shiftLat =
		(iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) +
		(iwSouthLat < mapSouthLat ? mapSouthLat - iwSouthLat : 0);

	// The center of the map
	var center = map.getCenter();

	// The new map center
	var centerX = center.lng() - shiftLng;
	var centerY = center.lat() - shiftLat;

	// center the map to the new shifted center
	map.setCenter(new google.maps.LatLng(centerY, centerX));

	// Remove the listener after panning is complete.
	google.maps.event.removeListener(this.boundsChangedListener_);
	this.boundsChangedListener_ = null;
};

