function PoiInfowindow(width, offset) {
	this.map_ = null;
	this.div_ = null;
	this.hiddendiv_ = null;
	this.contentdiv_ = null;

	this.width_ = width;

	if(typeof(offset) == 'undefined')
		offset = {x: 0, y: 0};

	this.offset_ = offset;

	this.timeout_ = null;
	this.visible_ = false;
	this.nohide_ = false;

	this.ready_ = false;

	this.poiid_ = '';
	this.point_ = null;
	this.content_ = null;
	this.marker_ = null;

	this.init();
}

PoiInfowindow.prototype = new GOverlay();

PoiInfowindow.prototype.init = function() {
	var div = $Div();
	div.className = 'infowindow';
	div.style.position = 'absolute';
	div.style.width = this.width_ + 'px';
	div.style.backgroundRepeat = 'no-repeat';
	div.style.display = 'none';
	div.style.zIndex = GOverlay.getZIndex(-90.0);

	div.onmouseover = function() {
		clearInfowindowTimeout();
	}
	div.onmouseout = function() {
		setInfowindowTimeout(500);
	}

	this.div_ = div;

	div = $Div();
	div.className = 'infowindow_content';

	this.contentdiv_ = div;

	this.div_.appendChild(this.contentdiv_);

	div = $Element('div');
	div.style.position = 'absolute';
	div.style.width = '1px';
	div.style.height = '1px';
	div.style.display = 'none';
	div.style.background = 'transparent';

	this.hiddendiv_ = div;
}

PoiInfowindow.prototype.setNeedle = function(horizontal, vertical) {
	if(horizontal == 'links') {
		this.contentdiv_.style.marginRight = '40px';
		this.contentdiv_.style.marginLeft = '0px';

		if(vertical == 'oben') {
			this.div_.style.backgroundImage = 'url(/map/images/needle_br_white.gif)';
			this.div_.style.backgroundPosition = 'right bottom';
		}
		else {
			this.div_.style.backgroundImage = 'url(/map/images/needle_tr.gif)';
			this.div_.style.backgroundPosition = 'right top';
		}
	}
	else {
		this.contentdiv_.style.marginLeft = '40px';
		this.contentdiv_.style.marginRight = '0px';

		if(vertical == 'oben') {
			this.div_.style.backgroundImage = 'url(/map/images/needle_bl_white.gif)';
			this.div_.style.backgroundPosition = 'left bottom';
		}
		else {
			this.div_.style.backgroundImage = 'url(/map/images/needle_tl.gif)';
			this.div_.style.backgroundPosition = 'left top';
		}
	}
}

PoiInfowindow.prototype.unload = function() {
	this.clear();

	this.map_ = null;
	this.div_ = null;

	this.poiid_ = '';
	this.point_ = null;
	this.content_ = null;
	this.contentdiv_ = null;

	this.marker_ = null;
}

PoiInfowindow.prototype.initialize = function(map) {
	this.map_ = map;

	if(this.div_ == null)
		this.init();

	this.div_.style.height = '';
	this.contentdiv_.style.height = '';

	this.map_.getPane(G_MAP_FLOAT_PANE).appendChild(this.hiddendiv_);

	//this.map_.getPane(G_MAP_FLOAT_PANE).appendChild(this.div_);

	document.body.appendChild(this.div_);
}

PoiInfowindow.prototype.setTimeout = function(duration) {
	this.timeout_ = setTimeout('clearInfowindow()', duration);
}

PoiInfowindow.prototype.clearTimeout = function() {
	clearTimeout(this.timeout_);
	this.timeout_ = null;
}

PoiInfowindow.prototype.remove = function() {
	this.setTimeout(500);
}

PoiInfowindow.prototype.clear = function() {
	this.clearTimeout();

	if(this.div_ && this.div_.parentNode)
		this.div_.parentNode.removeChild(this.div_);

	this.div_.style.display = 'none';

	this.visible_ = false;
}

PoiInfowindow.prototype.copy = function() {
	return new PoiInfowindow(this.width_);
}

PoiInfowindow.prototype.redraw = function(force) {
	if(!force)
		return;

	if(this.visible_ == true && this.timeout_ != null)
		this.clear();

	if(this.ready_ == false)
		return;

	this.visible_ = true;

	// Hoehe der ganzen Seiten bestimmen
	var bodyHeight = document.body.offsetHeight;

	// Die Groesse der Karte bestimmen
	var bounds = this.map_.getBounds();
	var sw = this.map_.fromLatLngToDivPixel(bounds.getSouthWest());
	var ne = this.map_.fromLatLngToDivPixel(bounds.getNorthEast());
	var mapheight = Math.abs(ne.y - sw.y);
	var mapwidth = Math.abs(ne.x - sw.x);

	//GLog.write('mapsize: ' + mapwidth + 'x' + mapheight);

	// Wo befindet sich der POI relativ zur Drag-Ebene der Karte
	var pos = this.map_.fromLatLngToDivPixel(this.marker_.getPoint());


	//GLog.write('pos: ' + pos.x + ' ' + pos.y);

	// Einen Hidden-Div an diesen Ort platzieren und die Koordianten
	// Relativ zum Karten-Div bestimmen. Wird benoetigt, um herauszufinden
	// auf welcher Seite das Infowindow angezeigt werden soll
	this.hiddendiv_.style.left = pos.x + 'px';
	this.hiddendiv_.style.top = pos.y + 'px';
	this.hiddendiv_.style.display = '';

	var rpos = this.getRelativePosition(this.hiddendiv_, this.map_.getContainer());

	//GLog.write('rpos: ' + rpos.x + ' ' + rpos.y);

	// Die absoluten Koordinaten des POI bestimmen
	var dragLayer = this.map_.getPane(G_MAP_MAP_PANE).parentNode;
	pos.x += parseInt(dragLayer.style.left);
	pos.y += parseInt(dragLayer.style.top);

	pos.x += this.map_.getContainer().offsetLeft;
	pos.y += this.map_.getContainer().offsetTop;

	// Offset fuer die Absoluten Koordinaten
	pos.x += this.offset_.x;
	pos.y += this.offset_.y;

	var icon = this.marker_.getIcon();

	var offsetX = -icon.infoWindowAnchor.x;
	var offsetY = -icon.infoWindowAnchor.y;

	// Standardmaessig wird das InfoWindow an der rechten unteren Ecke des Icon angezeigt
	offsetX += (icon.iconSize.width - icon.iconAnchor.x);
	offsetY += (icon.iconSize.height - icon.iconAnchor.y);

	// Infowindow links oder rechts darstellen?
	var horizontal = 'rechts';

	// Ist rechts genug Platz?
	if(mapwidth - rpos.x < this.width_)
		horizontal = 'links';
	// Falls links auch nicht genug Platz sein sollte, rechts darstellen
	if(rpos.x - sw.x < this.width_)
		horizontal = 'rechts';

	// Infowindow oben oder unten darstellen?
	var vertical = 'unten';

	// Da wo mehr Platz ist, wird es dargestellt
	var bottom = mapheight - rpos.y
	var top = mapheight - bottom;
	if(bottom < (mapheight / 2))
		vertical = 'oben';

	//GLog.write('top: ' + top + ' bottom: ' + bottom);

	//GLog.write(horizontal + ' ' + vertical);

	// Wenn es rechts nicht genug Platz hat, dann wird das Infowindow links angezeigt
	if(horizontal == 'links')
		offsetX += -(this.width_ + icon.iconSize.width);

	this.setNeedle(horizontal, vertical);

	// Das Infowindow sichtbar machen
	//this.div_.style.top = '-1000px';
	//this.div_.style.left = '-1000px';
	this.div_.style.display = '';
	var height = this.div_.offsetHeight;

	// Wenn das Infowindow nicht genug Platz hat, wird ein Scrollbalken eingeblendet
	if(vertical == 'oben') {
		if(height > top)
			this.contentdiv_.style.height = (top - 30) + 'px';
	}
	else {
		if(height > bottom)
			this.contentdiv_.style.height = (bottom - 30) + 'px';
	}



	this.div_.style.left = (pos.x + offsetX) + 'px';
	this.div_.style.bottom = '';
	this.div_.style.top = '';

	if(vertical == 'oben')
		this.div_.style.bottom = (bodyHeight - (pos.y + offsetY)) + 'px';
	else
		this.div_.style.top = (pos.y + offsetY) + 'px';


	//GLog.write('final height: ' + height);
}

PoiInfowindow.prototype.setPoi = function(poi) {
	this.clear();

	this.marker_ = poi.usedMarker;

	this.poiid_ = poi.id;
	this.point_ = poi.point;
	this.content_ = poi.getContent(setInfowindowContent);

	if(this.content_ == null)
		return;

	this.createContent();

	this.ready_ = true;
}

PoiInfowindow.prototype.createContent = function() {
	this.clearContent();

	this.contentdiv_.appendChild(this.content_);
}

PoiInfowindow.prototype.clearContent = function() {
	var n = this.contentdiv_;

	while(n.firstChild)
		n.removeChild(n.firstChild);
}

PoiInfowindow.prototype.getAbsolutePosition = function(node) {
	var n = node;
	var pos = {x: 0, y: 0};

	pos.x = n.offsetLeft;
	pos.y = n.offsetTop;

	while((n = n.offsetParent) != null) {
		pos.x += n.offsetLeft;
		pos.y += n.offsetTop;
	}

	return pos;
}

PoiInfowindow.prototype.getRelativePosition = function(child, parent) {
	var cpos = this.getAbsolutePosition(child);
	var ppos = this.getAbsolutePosition(parent);

	var pos = {x: 0, y: 0};

	pos.x = cpos.x - ppos.x;
	pos.y = cpos.y - ppos.y;

	return pos;
}

var _poiinfowindow = null;

// Interface fuer das Infowindow
function initInfowindow(width, offset) {
	_poiinfowindow = new PoiInfowindow(width, offset);
}

function setInfowindowTimeout(duration) {
	_poiinfowindow.setTimeout(duration);
}

function clearInfowindowTimeout() {
	_poiinfowindow.clearTimeout();
}

function clearInfowindow() {
	_poiinfowindow.clear();
}

function setInfowindowPoi(poi) {
	_poiinfowindow.setPoi(poi);
}

function getInfowindow() {
	return _poiinfowindow;
}

function setInfowindowContent(poiid, content) {
	if(content == null)
		return;

	if(_poiinfowindow.poiid_ != poiid)
		return;

	_poiinfowindow.content_ = content;
	_poiinfowindow.createContent();

	_poiinfowindow.redraw(true);
}

