/* ########################################################## */
// Detect if the browser is IE or not.
// If it is not IE, we assume that the browser is NS.
var IE = document.all?true:false
var running = false;
var endTime = null
var timerID = null

// If NS -- that is, !IE -- then set up for mouse capture
if (!IE) document.captureEvents(Event.MOUSEMOVE)

var best = new Array();

// Set-up to use getMouseXY function onMouseMove
document.onmousemove = getMouseXY;

// Temporary variables to hold mouse x-y pos.s
var tempX = 0
var tempY = 0

// Main function to retrieve mouse x-y pos.s

function getMouseXY(e) {
  if (IE) { // grab the x-y pos.s if browser is IE
    tempX = event.clientX + document.body.scrollLeft
    tempY = event.clientY + document.body.scrollTop
  } else {  // grab the x-y pos.s if browser is NS
    tempX = e.pageX
    tempY = e.pageY
  }
  // catch possible negative values in NS4
  if (tempX < 0){tempX = 0}
  if (tempY < 0){tempY = 0}
  // show the position values in the form named Show
  // in the text fields named MouseX and MouseY
  var windowWidth = window.document.body.offsetWidth; //window.innerWidth;
  var windowHeight =window.document.body.offsetHeight; //window.innerHeight;
  // pruefen welche ecke wir sind
  if (windowWidth/2 > tempX) {
        // links
        best[0] = 1;
  } else {
        best[0] = 2;
  }
  if (windowHeight/2 > tempY) {
        // oben
        best[1] = 1;
  } else {
        best[1] = 2;
  }
}
var totalSeconds = 2;
function startTimer(totalSecondsParam) {
    if (totalSecondsParam) {
	var MySeconds = totalSecondsParam;
    } else {
	var MySeconds = totalSeconds;
    }
    running = true
    now = new Date()
    now = now.getTime()
    endTime = now + (1000 * MySeconds);
    HideWindows();
}

function HideWindows() {
    var now = new Date()
    now = now.getTime()
    if (endTime - now <= 0) {
	running = false;
	// wir wollen alle infoboxen durchgehen und ausblenden
	//for (var i = 0;i<infobox.length;i++) {
	//	infobox[i].setMap(null);
	//}
        var anchor = window.location.hash;
        var tmp = anchor.split("/");
        var MyData = {"handwerker": tmp[tmp.length-2],"anchor":anchor};
	if (!IE) {
		logData(JSON.stringify(MyData),1);
	}
    } else {
	if (running) {
		timerID = setTimeout("HideWindows()",900);
	}
    }
}
/* ########################################################## */
/* An SmartInfoWindow is like an info window, but it displays
 * under the marker, opens quicker, and has flexible styling.
 * @param {Object} opts Passes configuration options.
 */
function SmartInfoWindow(opts) {
  google.maps.OverlayView.call(this);
  this.latlng_ = opts.position;
  this.content_ = opts.content;
  this.map_ = opts.map;
  this.height_ = 351;
  this.width_ = 280;
  this.marker_size = opts.size;
  this.marker_id = opts.marker_id;
  this.size_ = new google.maps.Size(this.height_, this.width_);
  this.offsetVertical_ = -this.height_;
  this.offsetHorizontal_ = 0;
  this.panned_ = false;
  this.setMap(this.map_);

  // We need to listen to bounds_changed event so that we can redraw
  // absolute position every time the map moves.
  // This is only needed because we append to body instead of map panes.
  var me = this;
  google.maps.event.addListener(this.map_, 'bounds_changed', function() {
    me.draw();
  });
}

/**
 * SmartInfoWindow extends GOverlay class from the Google Maps API
 */
SmartInfoWindow.prototype = new google.maps.OverlayView();

/**
 * Creates the DIV representing this SmartInfoWindow
 */
SmartInfoWindow.prototype.onRemove = function() {
  if (this.div_) {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
  }
};

/**
 * Called when the overlay is first added to the map.
 */
SmartInfoWindow.prototype.onAdd = function() {
	// alle elemente bis auf das letzte loeschen
	for (var i = 0;i<infobox.length-1;i++) {
	    infobox[i].setMap(null);
	}

  // Creates the element if it doesn't exist already.
  this.createElement();
};

/**
 * Redraw based on the current projection and zoom level.
 */
SmartInfoWindow.prototype.draw = function() {
  // Since we use bounds changed listener, projection is sometimes null
  if (!this.getProjection()) {
    return;
  }

  // This gives us the position in the tiles div.
  var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
  var centerPosition = this.getProjection().fromLatLngToDivPixel(this.map_.getCenter());
  var centerPositionReal = new google.maps.Point(this.map_.getDiv().offsetWidth/2, this.map_.getDiv().offsetHeight/2);
  // Figure out difference between map div and tiles div, so that we can
  // calculate position in map div
  var centerOffsetX = -centerPosition.x + centerPositionReal.x;
  var centerOffsetY = -centerPosition.y + centerPositionReal.y;

  if (!pixPosition) return;
  var alignment = this.getBestAlignment();
  var paddingTop = 0;
  var paddingLeft = 0;
  var widthLess = 0;
  /*
  switch (alignment) {
    case SmartInfoWindow.Align.ABOVE:
      this.width_ = 280;
      this.height_ = 351;
      image = 'infobox_above.gif';
      this.offsetX_ = -(this.width_ / 2 - 10);
      this.offsetY_ = -(this.height_ - 10);
      break;
    case SmartInfoWindow.Align.BELOW:
      this.width_ = 280;
      this.height_ = 351;
      image = 'infobox_below.gif';
      //this.offsetX_ = -(this.width_ / 2 - 10);
      this.offsetX_ = 0;
      this.offsetY_ = +12;
      paddingTop = 20;
      break;
    case SmartInfoWindow.Align.LEFT:
      this.width_ = 307;
      this.height_ = 326;
      image = 'infobox_left.gif';
      this.offsetX_ = -(this.width_) + 0;
      this.offsetY_ = -(this.height_ / 2 + 10);
      widthLess = 20;
      break;
    case SmartInfoWindow.Align.RIGHT:
      image = 'infobox_right.gif';
      this.width_ = 307;
      this.height_ = 326;
      this.offsetX_ = 6;
      this.offsetY_ = -(this.height_ / 2 + 10);
      paddingLeft = 20;
      widthLess = 20;
      break;
   }
  */
  var o_y = 0;
  var o_x = 0;
  this.padding = 0;
  this.paddingtop = 0;
  if (best == "1,1") {
	// oben links
	this.width_ = 282;
	this.height_ = 326;
	image = 'infobox_ol.gif';
	this.offsetX_ = -10;
	this.offsetY_ = -33;
	this.padding = 16;
	this.paddingtop = 10;
	if (IE) {
		this.padding = 14;
		this.paddingtop = 16;
	}
  }
  else if (best == "1,2") {
	// unten links
        this.width_ = 282;
        this.height_ = 326;
        image = 'infobox_ul.gif';
	if (this.marker_size >= 2) {
		var o_y = 15;
	}
        this.offsetX_ = -10;
        this.offsetY_ = -(this.height_)-15+parseInt(o_y);	
        this.padding = 16;
        this.paddingtop = 4;
        if (IE) {
                this.padding = 14;
                this.paddingtop = 10;
        }

  }
  else if (best == "2,1") {
	// oben rechts
        this.width_ = 282;
        this.height_ = 326;
        image = 'infobox_or.gif';
        if (this.marker_size >= 2) {
                var o_x = 15;
        }
        this.offsetX_ = -(this.width_)+10+parseInt(o_x);
        this.offsetY_ = 0-35;
        this.padding = 9;
        this.paddingtop = 10;
        if (IE) {
                this.padding = 4;
                this.paddingtop = 18;
        } 
  }
  else if (best == "2,2") {
	// unten rechts
        this.width_ = 282;
        this.height_ = 326;
        image = 'infobox_ur.gif';
        if (this.marker_size >= 2) {
                var o_x = 15;
		var o_y = 15;
        }
        this.offsetX_ = -(this.width_)+10+parseInt(o_x);
        this.offsetY_ = -(this.height_)-15+parseInt(o_y);
        this.padding = 9;
        this.paddingtop = 4;
        if (IE) {
                this.padding = 4;
                this.paddingtop = 14;
        }

  } else {
        // oben links
        this.width_ = 282;
        this.height_ = 326;
        image = 'infobox_ol.gif';
        this.offsetX_ = -10;
        this.offsetY_ = -33;
        this.padding = 16;
        this.paddingtop = 10;
        if (IE) {
                this.padding = 14;
                this.paddingtop = 16;
        }
  }
  // Now position our DIV based on the DIV coordinates of our bounds
  this.div_.style.width = this.width_ + 'px';
  this.div_.style.left = (pixPosition.x + this.offsetX_) + centerOffsetX + 'px';
  this.div_.style.height = this.height_ + 'px';
  this.div_.style.top = (pixPosition.y + this.offsetY_) + centerOffsetY + 'px';
  //this.div_.style.paddingTop = paddingTop + 'px';
  //this.div_.style.paddingLeft = paddingLeft + 'px';
  this.div_.style.background = 'url("/images/' + image + '")';
  this.div_.style.display = 'block';
  this.div_.style.zIndex = '200';
  this.div_.style.opacity = '0.9';
  this.div_.style.filter = "alpha(opacity=90)";

  this.wrapperDiv_.style.width = (this.width_- widthLess - 4) + 'px';
  //this.wrapperDiv_.style.height = this.height_ + 'px';
  //this.wrapperDiv_.style.marginTop = paddingTop + 'px';
  //this.wrapperDiv_.style.marginLeft = paddingLeft + 'px';
  this.wrapperDiv_.style.padding = this.padding + 'px';
  this.wrapperDiv_.style.paddingTop = this.paddingtop + "px";
  this.wrapperDiv_.style.overflow = 'hidden';
  this.wrapperDiv_.style.opacity = '1.0';
  this.wrapperDiv_.style.filter = "alpha(opacity=100)";
  this.wrapperDiv_.className = "infobox"; 
 /*if ((best == "1,2") || (best == "2,2")) { 
    this.wrapperDiv_.style.bottom = 0;
    this.wrapperDiv_.style.position = "absolute";
  } else {
    this.wrapperDiv_.style.top = 0;
    this.wrapperDiv_.style.position = "absolute";
  }
  */
  //this.wrapperDiv_.addEventListener("mouseover", startTimer(99), false);
  //startTimer(99);
 
  if (!this.panned_) {
    this.panned_ = true;
    this.maybePanMap();
  }
};

/**
 * Creates the DIV representing this SmartInfoWindow 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.
 */
SmartInfoWindow.prototype.createElement = function() {
  var panes = this.getPanes();
  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_ = document.createElement('div');
    div.style.border = '0px none';
    div.style.position = 'absolute';
    div.style.overflow = 'hidden';
    div.style.textAlign = 'center';
    var wrapperDiv = this.wrapperDiv_ = document.createElement('div');
    var _close = "";
    var contentDiv = document.createElement('div');
    if (typeof this.content_ == 'string') {
      if (_lock == true) {
	_close = "<span class='infobox_close'><a href='#' onclick=\"_lock=false;for (var i = 0;i<infobox.length;i++) { infobox[i].setMap(null); };\">x</a></span>";
      }
      wrapperDiv.innerHTML = _close+this.content_+"<div class='favorite'>"+ getFavoriteStar(this.marker_id)  +"</div>";
    } else {
      wrapperDiv.appendChild(this.content_);
    }

    function removeSmartInfoWindow(ib) {
      return function() {
		if (_lock == true) {
			return;
		}
		var pixPosition = ib.getProjection().fromLatLngToDivPixel(ib.latlng_);
		var centerPosition = ib.getProjection().fromLatLngToDivPixel(ib.map_.getCenter());
		var centerPositionReal = new google.maps.Point(ib.map_.getDiv().offsetWidth/2, ib.map_.getDiv().offsetHeight/2);
		// Figure out difference between map div and tiles div, so that we can
		// calculate position in map div
		var centerOffsetX = -centerPosition.x + centerPositionReal.x;
		var centerOffsetY = -centerPosition.y + centerPositionReal.y;
		var MyX = (pixPosition.x + ib.offsetX_) + centerOffsetX;
		var MyY = (pixPosition.y + ib.offsetY_) + centerOffsetY;
		// wir wollen nur schliessen, wenn wir nicht in einem feld sind
//                alert(MyY + " - " + (MyY+ib.height_-10) + " - " + tempY);
		if (((MyX+10 < tempX) && ((MyX+ib.width_-5) > tempX)) && ((MyY+10 < tempY) && ((MyY+ib.height_-10) > tempY))) {
			return "";
                }
		// wir wollen alle infoboxen durchgehen
		for (var i = 0;i<infobox.length;i++) {
            		infobox[i].setMap(null);
		}
		clearTimeout(timerID);
        //ib.setMap(null);
      };
    }


    //wrapperDiv.appendChild(contentDiv);
    //wrapperDiv.onmouseover = function() {startTimer(99)};
    div.appendChild(wrapperDiv);
    div.style.display = 'none';
    
    // Append to body, to avoid bug with Webkit browsers
    // attempting CSS transforms on IFRAME or SWF objects
    // and rendering badly.
    document.body.appendChild(div);

    google.maps.event.addDomListener(div, 'mouseout', removeSmartInfoWindow(this));
    //google.maps.event.addDomListener(wrapperDiv, 'mouseover', startTimer(99));

  } else if (div.parentNode != panes.floatPane) {
    // The panes have changed.  Move the div.
    div.parentNode.removeChild(div);
    panes.floatPane.appendChild(div);
  } else {
    // The panes have not changed, so no need to create or move the div.
  }
};

SmartInfoWindow.mouseFilter = function(e) {
  e.returnValue = 'true';
  e['handled'] = true;
}

/**
 * Closes infowindow
 */
SmartInfoWindow.prototype.close = function() {
  this.setMap(null);
};

/**
 * Pan the map to fit the SmartInfoWindow,
 * if its top or bottom corners aren't visible.
 */
SmartInfoWindow.prototype.maybePanMap = function() {
  // if we go beyond map, pan map
  var map = this.map_;
  var projection = this.getProjection();
  var bounds = map.getBounds();
  if (!bounds) return;

  // The dimension of the infowindow
  var iwWidth = this.width_;
  var iwHeight = this.height_;

  // The offset position of the infowindow
  var iwOffsetX = this.offsetX_;
  var iwOffsetY = this.offsetY_;

  var anchorPixel = projection.fromLatLngToDivPixel(this.latlng_);
  var bl = new google.maps.Point(anchorPixel.x + iwOffsetX + 20,
      anchorPixel.y + iwOffsetY + iwHeight);
  var tr = new google.maps.Point(anchorPixel.x + iwOffsetX + iwWidth,
      anchorPixel.y + iwOffsetY);
  var sw = projection.fromDivPixelToLatLng(bl);
  var ne = projection.fromDivPixelToLatLng(tr);

  // The bounds of the infowindow
  if (!map.getBounds().contains(ne) || !map.getBounds().contains(sw)) {
    // wir wollen nicht, dass die karte sich bewegt
    //map.panToBounds(new google.maps.LatLngBounds(sw, ne));
  }
};

/**
 * @enum {number}
 */
SmartInfoWindow.Align = {
  ABOVE: 0,
  LEFT: 1,
  RIGHT: 2,
  BELOW: 3
};

/**
 * Finds best alignment for infowindow.
 * @return {number} Alignment.
 */
SmartInfoWindow.prototype.getBestAlignment = function() {
  var bestAlignment = SmartInfoWindow.Align.LEFT;
  var minPan = 0;

  for (var alignment in SmartInfoWindow.Align) {
    var alignment = SmartInfoWindow.Align[alignment];
    var panValue = this.getPanValue(alignment);
    if (panValue > minPan) {
      minPan = panValue;
      bestAlignment = alignment;
    }
  }
  return bestAlignment;
};

/**
 * Calculates distance of corner for each alignment.
 * @param {number} alignment An alignment constant.
 * @return {number} Distance for that alignment.
 */
SmartInfoWindow.prototype.getPanValue = function(alignment) {
  var mapSize = new google.maps.Size(this.map_.getDiv().offsetWidth,
      this.map_.getDiv().offsetHeight);
  var bounds = this.map_.getBounds();
  var sideLatLng;
  switch (alignment) {
    case SmartInfoWindow.Align.ABOVE:
      sideLatLng = new google.maps.LatLng(bounds.getNorthEast().lat(),
          this.latlng_.lng());
      break;
    case SmartInfoWindow.Align.BELOW:
      sideLatLng = new google.maps.LatLng(bounds.getSouthWest().lat(),
          this.latlng_.lng());
      break;
    case SmartInfoWindow.Align.RIGHT:
      sideLatLng = new google.maps.LatLng(this.latlng_.lat(),
          bounds.getNorthEast().lng());
      break;
    case SmartInfoWindow.Align.LEFT:
      sideLatLng = new google.maps.LatLng(this.latlng_.lat(),
          bounds.getSouthWest().lng());
      break;
  }
  var dist = SmartInfoWindow.distHaversine(this.latlng_.lat(), this.latlng_.lng(),
      sideLatLng.lat(), sideLatLng.lng());
  return dist;
};


/**
 * Converts degrees to radians.
 * @param {number} num Angle in degrees.
 * @return {number} Angle in radians.
 */
SmartInfoWindow.toRad = function(num) {
    return num * Math.PI / 180;
}

/**
 * Calculates distance between two coordinates.
 * @param {number} lat1 Latitude of first coord.
 * @param {number} lon1 Longitude of second coord.
 * @param {number} lat2 Latitude of second coord.
 * @param {number} lon2 Longitude of second coord.
 * @return {number} The distance.
 */
SmartInfoWindow.distHaversine = function(lat1, lon1, lat2, lon2) {
  var R = 6371; // earth's mean radius in km
  var dLat = SmartInfoWindow.toRad(lat2 - lat1);
  var dLon = SmartInfoWindow.toRad(lon2 - lon1);
  lat1 = SmartInfoWindow.toRad(lat1), lat2 = SmartInfoWindow.toRad(lat2);

  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
          Math.cos(lat1) * Math.cos(lat2) *
          Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;
  return d;
}




