/*
Copyright 2005-2009 James Tolley - http://www.bitperfect.com | http://www.gmaptools.com
All rights reserved.
This software is released under the LGPL. (http://www.opensource.org/licenses/lgpl-license.php)

  BpTooltip - a bare-bones tooltip class

TODO:
  test basic sanity of existing code
  change existing tests completely
  manage the current marker & listeners

  future development:
    more window-like functionality?
    clickable?
    popup menu subclass?

*/

(function() {

function BpTooltip(latlng, html) {
  // the true argument will initially hide the label
  BpLabel.call(this, latlng, html, true, 'nw');

  this.setPane(G_MAP_FLOAT_SHADOW_PANE);
  this._bp = {};
  this._bp._ignore = true;
}

BpTooltip.prototype = new BpLabel();

BpTooltip.prototype.initialize = function(map) {
  BpLabel.prototype.initialize.call(this, map);

  // setup the code to reposition the tooltip on zoom
  if (typeof this._onZoomListener == 'undefined') {
    this._onZoomListener = GEvent.addListener(map, 'zoomend', GEvent.callback(this, this.onZoomEnd));
  }

  return this._div;
};

BpTooltip.prototype.onZoomEnd = function() {
  if(this._marker) {
    this.redraw();
  }
};

BpTooltip.prototype.copy = function() {
  return new BpTooltip(this._latlng, this._html);
};

BpTooltip.prototype.setMarker = function(marker) {
  this._marker = marker;
  if(!marker) {
    this.hide();
    this.setHtml('');
  }
  else if (typeof marker.getTooltipHtml === 'function') {
    this.setHtml(marker.getTooltipHtml());
  }
};

BpTooltip.prototype.getMarker = function() {
  return this._marker;
};

// if there's no marker, there's nothing to do
// always force; when the marker moves, we move
BpTooltip.prototype.redraw = function(force) {
  var m = this.getMarker();
  if (m) {
//    this.setHtml( m.getTooltipHtml() );
    m.redraw();
    var point = m.getTooltipPoint();

    this._div.style.top  = point.y + 'px';
    this._div.style.left = point.x + 'px';
  }
};

BpTooltip.prototype.remove = function() {
  if (this._onZoomListener) {
    GEvent.removeListener(this._onZoomListener);
    delete this._onZoomListener;
  }

  BpLabel.prototype.remove.call(this);
};

if (!window.BpTooltip) {
  window.BpTooltip = BpTooltip;
}

})();

/*
Copyright 2005-2009 James Tolley - http://www.bitperfect.com | http://www.gmaptools.com
All rights reserved.
This software is released under the LGPL. (http://www.opensource.org/licenses/lgpl-license.php)

    setup tooltip methods of GMarkers:
    
    marker.setTooltip(BpTooltip_object, html);
    var tt = marker.getTooltip();
    var html = marker.getTooltipHtml();
    marker.setTooltipHtml(html);
    //var latlng = marker.getTooltipLatLng();
    var point = marker.getTooltipPoint(); // div pixel
    marker.setMaintainTooltip(bool);
    marker.removeTooltip();

0.1  - initial release
0.11 - requires manual calling
       optional constructor argument
       better vertical placement in relation to marker: centered

TODO
  use ._bp to hide properties
  the tooltip doesn't show all of itself when the marker is near the top or bottom of the map
  the tooltip will show on the left of the marker if there's not enough room to the right, even if
    there's more room to the right.
    1) count pixels to find out if there's enough room on the right (don't use latlngs)
    2) count pixels to find if there's more room on the right than on the left

*/

if (!window.setupSetTooltip) {

  function mk_bp(m) {
    if (typeof m._bp === 'undefined') {
      m._bp = {};
    }
  }

  window.setupSetTooltip = function(constructor) {
    if (typeof(constructor) != 'function') {
      constructor = GMarker;
    }

    if (typeof constructor.prototype.setTooltip == 'function') {
      return;
    }

    constructor.prototype.removeTooltip = function(){
      mk_bp(this);
      if (this._bp._ttOverListener) {
        GEvent.removeListener(this._bp._ttOverListener);
        delete this._bp._ttOverListener;
        GEvent.removeListener(this._bp._ttOutListener);
        delete this._bp._ttOutListener;
        var tt = this.getTooltip();
        if(tt.getMarker() === this) {
          tt.setMarker();
        }
        delete this._bp._tt;
      }
    }

    constructor.prototype.setTooltip = function(tt, html) {
      mk_bp(this);
      // remove tooltip
      if(!tt && this.getTooltip()) {
        this.removeTooltip();
        return;
      }

      this._bp._tt = tt;
      this._bp._ttHtml = html;
  
      var mouseOverHandler = function() {
        var tt = this.getTooltip();
        if(tt) {
          tt.setMarker(this);
//          tt.setHtml(this._bp._ttHtml);
          tt.redraw();
          tt.show();
        }
      };

      this._bp._ttOverListener = GEvent.addListener(this, 'mouseover', mouseOverHandler);

      var mouseOutHandler = function() {
        var tt = this.getTooltip();
        if(tt && !this._bp._ttMaintain) {
          tt.setMarker();
        }
      };

      this._bp._ttOutListener = GEvent.addListener(this, 'mouseout', mouseOutHandler);
    };

    constructor.prototype.getTooltip = function() {
      mk_bp(this);
      return this._bp._tt;
    };

    constructor.prototype.getTooltipHtml = function() {
      mk_bp(this);
      return this._bp._ttHtml;
    };

    constructor.prototype.setTooltipHtml = function(html) {
      mk_bp(this);
      this._bp._ttHtml = html;
    };

    constructor.prototype.getTooltipPoint = function() {
      mk_bp(this);
      var margin = 5; // px to the right (or left) of the icon

      var tt = this.getTooltip();
      var map = tt.getMap();
      var pixel = map.fromLatLngToDivPixel(this.getLatLng());
      var icon = this.getIcon();
      pixel.x -= icon.iconAnchor.x;
      pixel.x += icon.iconSize.width;
      pixel.x += margin;

      pixel.y -= icon.iconAnchor.y;
      pixel.y += 0.5 * icon.iconSize.height;
      pixel.y -= 0.5 * tt.getHeight();

      // how many pixels are between the margin and the right side of the map?
      var nePixel = map.fromLatLngToDivPixel(map.getBounds().getNorthEast());
      var ttWidth = tt.getWidth();
      if(nePixel.x < pixel.x + ttWidth) {
        pixel.x -= 2 * margin;
        pixel.x -= icon.iconSize.width;
        pixel.x -= ttWidth;
      }
      return pixel;
    };

    constructor.prototype.showTooltip = function() {
      mk_bp(this);
      var tt = this.getTooltip();
      if(!tt) {
        return;
      }
      tt.setMarker(this);
      tt.redraw();
      tt.show();
    };
  
    constructor.prototype.hideTooltip = function() {
      mk_bp(this);
      var tt = this.getTooltip();
      if(!tt) {
        return;
      }
      tt.hide();
    };
  
    constructor.prototype.setMaintainTooltip = function(bool) {
      mk_bp(this);
      this._bp._ttMaintain = bool;
      if(bool) {
        this.showTooltip();
      }
      else {
        this.hideTooltip();
      }
    };
  }
  if (GMarker) {
    setupSetTooltip(GMarker);
  }
  else {
    alert('BpTooltip should be loaded after the Google Maps API');
  }
  setupSetTooltip.version = 0.12;
}
