/*
0.12 - fixed flicker issue
0.13 - initially hidden feature added
0.14 - added initial ZIndex feature
			 return div from initialize()
			 if no zIndex has been specified,
			 	 then setPoint() changes the zIndex appropriately

*/
function BpLabel() {

var bpId = 0;
function BpLabel(bpPoint,bpLabel,bpClassName,bpAnchor,bpHide) {
  this.bpPoint     = bpPoint;
  this.bpLabel     = bpLabel;
  this.bpClassName = bpClassName || '';
  this.bpAnchor    = bpAnchor    || 'center';
  this.bpHide      = bpHide      || false;

  this.bpOpacity   = 85;
  this.bpPane      = G_MAP_FLOAT_SHADOW_PANE;
  this.bpId        = ++bpId;
  this.isBpLabel   = true;
}

BpLabel.prototype = new GOverlay();

var bpPrototype = BpLabel.prototype;

var bpInfoWindowOpener = null;
var bpInfoWindowListener = false;
bpPrototype.initialize = function(bpMap,bpHide) {
  this.bpMap = bpMap;

  if(!bpInfoWindowListener)
    bpInfoWindowListener = GEvent.addListener(bpMap,'infowindowclose',function(){
      bpInfoWindowOpener = null;
    });

  var bpDiv = document.createElement('div');
  bpDiv.innerHTML = '<div class=\'' + this.bpClassName + '\'>' + this.bpLabel + '</div>';
  bpDiv.style.position = 'absolute';

  if(!this.bpClassName) {
    var bpStyle = bpDiv.firstChild.style;
    bpStyle.border          = '1px solid black';
    bpStyle.backgroundColor = 'white';
    bpStyle.filter          = 'alpha(opacity:' + this.bpOpacity + ')';
    bpStyle.KHTMLOpacity    = this.bpOpacity / 100;
    bpStyle.MozOpacity      = this.bpOpacity / 100;
    bpStyle.opacity         = this.bpOpacity / 100;
    bpStyle.fontWeight      = 'bold';
    bpStyle.whiteSpace      = 'nowrap';
    bpStyle.paddingRight    = '3px';
    bpStyle.paddingLeft     = '3px';
  }

  if(bpHide || this.bpHide)
    bpDiv.style.display = 'none';

  this.bpDiv = bpDiv;
  this.redraw(true); //alert(this.bpDiv.style.top + ":" + this.bpDiv.style.left);
  bpMap.getPane(this.bpPane).appendChild(bpDiv);

  this.bpGetSize();
	if(this.bpCursor)
		this.setCursor(this.bpCursor);
	if(typeof(this.bpOpacity) != 'undefined')
		this.setOpacity(this.bpOpacity);

  if(this.getHoverLine())
    this.setHoverLine(this.getHoverLine());
    
  this.setZIndex();

  return bpDiv;
};

bpPrototype.getId = function() {
	return this.bpId;
};

bpPrototype.bpGetOffMapPoint = function() {
  var bpMap = this.bpMap;
	var bpCenter = bpMap.getCenter();
	var bpSpan = bpMap.getBounds().toSpan();
  return new GLatLng(bpCenter.lat() - bpSpan.lat(),bpCenter.lng());
};

bpPrototype.bpGetSize = function() {
  var bpP;
  var bpIsHidden = !this.isVisible();
  if(bpIsHidden) {
    bpP = this.getPoint();
    var offMapPoint = this.bpGetOffMapPoint();
    this.setPoint(offMapPoint);
    this.display(true);
  }

  this.bpWidth  = this.bpGetWidth(this.bpDiv.firstChild);
  this.bpHeight = this.bpGetHeight(this.bpDiv.firstChild);

  if(bpIsHidden) {
    this.display(false);
    this.setPoint(bpP);
  }
};

bpPrototype.getWidth = function() {
  return this.bpWidth;
};

bpPrototype.getHeight = function() {
  return this.bpHeight;
};

bpPrototype.getHtml = function() {
	return this.bpLabel;
};

bpPrototype.setHtml = function(bpLabel) {
	this.bpLabel = bpLabel;
  
  if(!this.bpMap)
    return;

  this.bpDiv.firstChild.innerHTML = this.bpLabel;
  if(this.isVisible()) {
    this.hide(); this.show(); // some browsers need help resizing the div
  }
  this.bpGetSize();
  this.redraw(true);
};

bpPrototype.getPoint = function() {
	return this.bpPoint;
};

bpPrototype.setPoint = function(bpPoint) {
  this.bpPoint = bpPoint;
	if(typeof(this.bpZIndex) == 'undefined')
		this.setZIndex();
  this.redraw(true);
};

bpPrototype.getOpacity = function() {
	return this.bpOpacity;
};

bpPrototype.setOpacity = function(bpOpacity) {
	if(bpOpacity < 0)   bpOpacity = 0;
	if(bpOpacity > 100) bpOpacity = 100;

	this.bpOpacity = bpOpacity;

	var bpDiv = this.bpDiv;
	if(bpDiv) {
		var bpPercent = bpOpacity / 100;
		if(typeof(bpDiv.style.filter) == 'string')
		  bpDiv.style.filter = 'alpha(opacity:' + bpOpacity + ')';

		if(typeof(bpDiv.style.KHTMLOpacity) == 'string')
		  bpDiv.style.KHTMLOpacity = bpPercent;

		if(typeof(bpDiv.style.MozOpacity) == 'string')
		  bpDiv.style.MozOpacity = bpPercent;

		if(typeof(bpDiv.style.opacity) == 'string')
		  bpDiv.style.opacity = bpPercent;
	}
};

bpPrototype.getClassName = function() {
	return this.bpClassName;
};

bpPrototype.setClassName = function(bpClassName) {
	this.bpClassName = bpClassName;

  this.bpDiv.firstChild.className = this.bpClassName;

  this.bpGetSize();
  this.redraw(true);
};

bpPrototype.getUserData = function() {
	return this.bpUserData;
};

bpPrototype.setUserData = function(bpData) {
  this.bpUserData = bpData;
};

bpPrototype.getPane = function() {
  return this.bpPane;
};

bpPrototype.setPane = function(bpPane) {
  this.bpPane = bpPane;
};

bpPrototype.getCursor = function() {
	return this.bpCursor;
};

bpPrototype.setCursor = function(bpCursor) {
	this.bpCursor = bpCursor;
	var bpDiv = this.bpDiv;
	if(bpDiv) {
		try {
			bpDiv.style.cursor = bpCursor;
		} catch(e) {
			bpDiv.style.cursor = (bpCursor == 'pointer' ? 'hand' : 'pointer');
		}
	}
};

bpPrototype.getHoverLine = function() {
	return this.bpOnHoverLine;
};

bpPrototype.setHoverLine = function(bpLine) {
	this.bpOnHoverLine = bpLine;

  if(!this.bpMap)
    return;

  if(this.bpOnHoverLine && !this.bpOnHoverListener) {
    this.bpOnOverListener = GEvent.bindDom(this.getEventTarget(),'mouseover',this,this.bpOnMouseOver);
    this.bpOnOutListener  = GEvent.bindDom(this.getEventTarget(),'mouseout',this,this.bpOnMouseOut);
  } else if(this.bpOnHoverListener) {
    GEvent.removeListener(this.bpOnOverListener);
    delete this.bpOnOverListener;
    GEvent.removeListener(this.bpOnOutListener);
    delete this.bpOnOutListener;
  }
};

bpPrototype.bpOnMouseOver = function() {
  if(this.bpOnHoverLine)
    this.bpMap.addOverlay(this.bpOnHoverLine);
};

bpPrototype.bpOnMouseOut = function() {
  if(this.bpOnHoverLine)
    this.bpMap.removeOverlay(this.bpOnHoverLine);
};

BpLabel.getInfoWindowOpener = function() {
  return bpInfoWindowOpener;
};

BpLabel.bpSetInfoWindowOpener = function(bpOpener) {
  bpInfoWindowOpener = bpOpener;
};

var bpInfoWindowMethods = ['openInfoWindow','openInfoWindowHtml','openInfoWindowTabs','openInfoWindowTabsHtml','openInfoWindowXslt','showMapBlowup'];
for(var i = 0; i < bpInfoWindowMethods.length; i++) {
bpPrototype[bpInfoWindowMethods[i]] = function() {
  var bpMap = this.bpMap;
  if(!bpMap)
    return;

  var bpA = new Array(this.bpGetIwPoint());
  for(var i = 0; i < arguments.length; i++)
    bpA.push(arguments[i]);

  bpMap.closeInfoWindow();
  BpLabel.bpSetInfoWindowOpener(this);
  bpMap[bpInfoWindowMethods[i]].apply(bpMap,bpA);
};
}

bpPrototype.bpGetAnchorOffset = function() {
  var bpPoint = new GPoint(0,0);

  var bpWidth  = this.getWidth();
  var bpHeight = this.getHeight();

  switch(this.getAnchor()) {
    case 'n':
      bpPoint.x -= Math.floor(bpWidth/2);
      break;
    case 'ne':
      bpPoint.x -= bpWidth;
      break;
    case 'e':
      bpPoint.x -= bpWidth;
      bpPoint.y -= Math.floor(bpHeight/2);
      break;
    case 'se':
      bpPoint.x -= bpWidth;
      bpPoint.y -= bpHeight;
      break;
    case 's':
      bpPoint.x -= Math.floor(bpWidth/2);
      bpPoint.y -= bpHeight;
      break;
    case 'sw':
      bpPoint.y -= bpHeight;
      break;
    case 'w':
      bpPoint.y -= Math.floor(bpHeight/2);
      break;
    case 'center':
      bpPoint.x -= Math.floor(bpWidth/2);
      bpPoint.y -= Math.floor(bpHeight/2);
  }

  return bpPoint;
};

bpPrototype.getInfoWindowOffset = function() {
  return this.bpIwOffset;
};

bpPrototype.setInfoWindowOffset = function(bpPoint) {
  this.bpIwOffset = bpPoint;
};

bpPrototype.bpGetIwPoint = function() {
  var bpX = parseInt(this.bpDiv.style.left);
  var bpY = parseInt(this.bpDiv.style.top);

  bpX += Math.round(this.getWidth()/2);
  bpY += Math.round(this.getHeight()/2);
    
  var bpPoint = new GPoint(bpX,bpY);

  if(this.bpIwOffset) {
    bpPoint.x += this.bpIwOffset.x;
    bpPoint.y += this.bpIwOffset.y;
  }

  return this.bpMap.fromDivPixelToLatLng(bpPoint);
};

bpPrototype.getAnchor = function() {
	return this.bpAnchor;
};

bpPrototype.setAnchor = function(bpAnchor) {
	if(new RegExp('^(n|s)?(e|w)?$','i').test(bpAnchor) && bpAnchor != '')
		this.bpAnchor = bpAnchor;
	else
		this.bpAnchor = 'center';
	this.redraw(true);
};

bpPrototype.getEventTarget = function() {
  if(!this.bpMap)
    return;

	return this.bpDiv.firstChild;
};

bpPrototype.getMap = function() {
	return this.bpMap;
};

bpPrototype.isMapped = function() {
	return (this.bpDiv && this.getMap() && this.bpDiv.parentNode === this.getMap().getPane(this.getPane())) ? true : false;
};

bpPrototype.isVisible = function() {
  if(!this.isMapped())
    return false;

	return this.bpDiv.style.display != 'none';
};

bpPrototype.show = function() {
	this.display(true);
};

bpPrototype.hide = function() {
	this.display(false);
};

bpPrototype.display = function(bpBool) {
  if(!this.bpMap)
    return;

  if(bpBool) {
    this.bpDiv.style.display = '';
  } else {
    this.bpDiv.style.display = 'none';
  }
};

bpPrototype.getZIndex = function(bpLat) {
  if(typeof(this.bpZIndex) != 'undefined')
    return this.bpZIndex;

  if(arguments.length == 0)
    bpLat = this.getPoint().lat();

  return GOverlay.getZIndex(bpLat);
};

bpPrototype.setZIndex = function(bpZi) {
  if(arguments.length == 0) {
    this.setZIndex(this.getZIndex());
    delete this.bpZIndex;
  } else {
	  this.bpZIndex = bpZi;
	  this.getEventTarget().parentNode.style.zIndex = bpZi;
	}
};

// the point of this is to set the top & left styles of the div
// if the label has not been added to the pane yet (and the anchor is not 'nw'), we'll 
// need to add it off-map, then get the height & width of the div in 
// order to find out the left & top.
// In that case, we'll remove it again from the pane.
bpPrototype.redraw = function(bpReally) {
  if(this.isMapped()) {
    var bpP = this.bpMap.fromLatLngToDivPixel(this.bpPoint);
    var offset = this.bpGetAnchorOffset();
    bpP.x += offset.x;
    bpP.y += offset.y;

    this.bpDiv.style.top  = bpP.y + 'px';
    this.bpDiv.style.left = bpP.x + 'px';
  } else {
    //  find an off-map pixel
    var px = this.getMap().fromLatLngToDivPixel(this.bpGetOffMapPoint());
    // add it to the map
    this.bpDiv.style.top  = px.y + 'px';
    this.bpDiv.style.left = px.x + 'px';
    this.getMap().getPane(this.getPane()).appendChild(this.bpDiv);
    var bpPrevDisplay = this.bpDiv.style.display;
    this.bpDiv.style.display = '';
    // get the size
    this.bpGetSize();
    // remove it from the map
    this.getMap().getPane(this.getPane()).removeChild(this.bpDiv);
    this.bpDiv.style.display = bpPrevDisplay;
  }
};

bpPrototype.copy = function() {
  var bpCopy = new BpLabel(this.bpPoint,this.bpLabel,this.bpClassName,this.bpAnchor);
  bpCopy.setOpacity(this.getOpacity());
  bpCopy.setHoverLine(this.getHoverLine());
  bpCopy.setZIndex(this.getZIndex());
  bpCopy.setPane(this.getPane());
  bpCopy.setUserData(this.getUserData());
  bpCopy.setCursor(this.getCursor());
  bpCopy.setInfoWindowOffset(this.getInfoWindowOffset());
  return bpCopy;
};

bpPrototype.remove = function() {
  this.bpDiv.parentNode.removeChild(this.bpDiv);
  delete this.bpMap;
};

bpPrototype.bpGetHeight = function(bpDiv) {
  if(typeof(bpDiv.offsetHeight) != 'undefined')
    return bpDiv.offsetHeight;
  else if(typeof(bpDiv.style.pixelHeight) != 'undefined')
    return bpDiv.style.pixelHeight;
  
  return 0;
};

bpPrototype.bpGetWidth = function(bpDiv) {
  if(typeof(bpDiv.offsetWidth) != 'undefined')
    return bpDiv.offsetWidth;
  else if(typeof(bpDiv.style.pixelWidth) != 'undefined')
    return bpDiv.style.pixelWidth;
  
  return 0;
};

window.BpLabel = BpLabel;
}
BpLabel();
