// This BDCCCircle is a VML/SVG overlay that shows a circle on the map
// You can specify the border width, colour and opacity 
// as well as whether the circle is filled or not and the fill colour and opacity.
// The radius of the circle is given in kilometers.
//
// For a gradiant fill, both fillColor and fillOpacity may be an array of length 2
//
// Events are 'click','mouseover' and 'mouseout' 
//
// If targeting MSIE remember to include the VML header material (see GMaps docs)
//
// Bill Chadwick 2007

var BDCCCircleId;

var BDCCCircleSvgRoot;

function BDCCCircle(point, radiusKm, strokeColor, strokeWeight, strokeOpacity, fill, fillColor, fillOpacity, tooltip) {

  this.point_ = point;
  this.radiusKm_ = radiusKm;
  this.lineColour_ = strokeColor || "#888888";
  this.lineWidth_ = strokeWeight || 3;
  this.lineOpacity_ = strokeOpacity || 0.5;
  this.fill_ = fill || false;
  
  this.fillColour_ = fillColor || "#444444";//save original object for copy
  if (this.fillColour_.constructor.toString().indexOf("Array") == -1){
      this.fillColour1_ = this.fillColour_;
      this.fillColour2_ = null;
  }
  else if (this.fillColour_.length == 2){
      this.fillColour1_ = this.fillColour_[0] || "#222222";
      this.fillColour2_ = this.fillColour_[1] || "#888888";
  }
  else{
      this.fillColour1_ = this.fillColour_[0] || "#444444";
      this.fillColour2_ = null;
  }
  
  this.fillOpacity_ = fillOpacity || 0.3;//save orgiginal for copy
  if (this.fillOpacity_.constructor.toString().indexOf("Array") == -1){
      this.fillOpacity1_ = this.fillOpacity_;
      this.fillOpacity2_ = null;
  }
  else if (this.fillOpacity_.length == 2){
      this.fillOpacity1_ = this.fillOpacity_[0] || 0.1;
      this.fillOpacity2_ = this.fillOpacity_[1] || 0.9;
  }
  else
  {
      this.fillOpacity1_ = this.fillOpacity_[0] || 0.5;
      this.fillOpacity2_ = null;
  }
  
  this.tooltip_ = tooltip;
  this.usesVml_ = (navigator.userAgent.indexOf("MSIE") != -1);
  
  if(BDCCCircleId == null)
    BDCCCircleId = 0;
  else
    BDCCCircleId += 1;
    
  this.gradId_ = "BDCCCircleGradient" + BDCCCircleId.toString();//for SVG gradient
   
}
BDCCCircle.prototype = new GOverlay();

//Get/Set methods

//Point or center
BDCCCircle.prototype.getPoint = function(){
    return this.point_;
}
BDCCCircle.prototype.setPoint = function(point){
    this.point_ = point;
    this.redraw(false);
}

// Radius
BDCCCircle.prototype.getRadiusKm = function(){
    return this.radiusKm_;
}
BDCCCircle.prototype.setRadiusKm = function(radiusKm){
    this.radiusKm_ = radiusKm;
    this.redraw(false);
}

//Stroke (line) colour
BDCCCircle.prototype.setStrokeColor = function(color) {
    this.lineColour_ = color;
    if(this.usesVml_){
        this.vmlCircle_.stroke.color = this.lineColour_;
    }
    else{
        this.svgNode_.setAttribute("stroke",this.lineColour_);
    }
}
BDCCCircle.prototype.getStrokeColor = function() {
    return this.lineColour_;
}

//Stroke (line) weight (pixels)
BDCCCircle.prototype.setStrokeWeight = function(weight) {
    this.lineWidth_ = weight;
    if(this.usesVml_){
        this.vmlCircle_.stroke.weight = this.lineWidth_.toString()+"px";   
    }
    else{
        this.svgNode_.setAttribute("stroke-width",this.lineWidth_.toString()+"px");
    }
}
BDCCCircle.prototype.getStrokeWeight = function() {
    return this.lineWidth_;
}

//Stroke (line) opacity 0.0 (transparent) to 1.0 (opaque)
BDCCCircle.prototype.setStrokeOpacity = function(opacity) {
    this.lineOpacity_ = opacity;
    if(this.usesVml_){
        this.vmlCircle_.stroke.opacity = this.lineOpacity_;
    }
    else{
        this.svgNode_.setAttribute("stroke-opacity",this.lineOpacity_);
    }
}
BDCCCircle.prototype.getStrokeOpacity = function() {
    return this.lineOpacity_;
}

//Fill colour
BDCCCircle.prototype.setFillColor = function(fillColor) {

  this.fillColour_ = fillColor || "#444444";//save original object for copy
  if (this.fillColour_.constructor.toString().indexOf("Array") == -1){
      this.fillColour1_ = this.fillColour_;
      this.fillColour2_ = null;
  }
  else if (this.fillColour_.length == 2){
      this.fillColour1_ = this.fillColour_[0] || "#222222";
      this.fillColour2_ = this.fillColour_[1] || "#888888";
  }
  else{
      this.fillColour1_ = this.fillColour_[0] || "#444444";
      this.fillColour2_ = null;
  }

    if(this.usesVml_)
        this.vmlFillHelper();
    else
        this.svgFillHelper();
}
BDCCCircle.prototype.getFillColor = function() {
    return this.fillColour_;
}

//Fill helper for vml, need this as can't script opacity2
BDCCCircle.prototype.vmlFillHelper = function() {
    this.vmlCircle_.removeChild(this.vmlCircle_.children[1]);
    
    f = "<v:fill";
    
    if(!this.fill_)
        f += " type='none'"; 
    else if((this.fillOpacity2_ != null) || (this.fillColour2_ != null))
        f += " type='gradientradial' focusposition='0.5,0.5' focussize='0,0' method='linear'";
    else
        f += " type='solid'"; 
        
    f += " opacity=" + this.fillOpacity1_;
    if(this.fillOpacity2_ != null)
        f += " o:opacity2=" + this.fillOpacity2_;
    else if (this.fillColour2_ != null)
        f += " o:opacity2=" + this.fillOpacity1_;   
    f += " color=" + this.fillColour1_;
    if(this.fillColour2_ != null)
        f += " color2=" + this.fillColour2_;     
    else if(this.fillOpacity2_ != null)
        f += " color2=" + this.fillColour1_;     
    f += "/>";
    
    this.vmlCircle_.appendChild(document.createElement(f));
}


BDCCCircle.prototype.svgFillHelper = function() {

    if(!this.fill_){
        this.svgNode_.setAttribute("fill-opacity","0.0");    
        this.svgNode_.setAttribute("pointer-events","visibleStroke");
        }
    else if((this.fillOpacity2_ == null) && (this.fillColour2_ == null)){
        this.svgNode_.setAttribute("fill",this.fillColour1_);
        this.svgNode_.setAttribute("fill-opacity",this.fillOpacity1_);    
        this.svgNode_.setAttribute("pointer-events","visibleFill");
        }
    else{
        this.svgNode_.setAttribute("fill","url(#" + this.gradId_ + ")");        
    
        this.svgStop2_.setAttribute("stop-opacity",this.fillOpacity1_);
        if(this.fillOpacity2_ != null)
            this.svgStop1_.setAttribute("stop-opacity",this.fillOpacity2_);
        else if (this.fillColour2_ != null)
            this.svgStop1_.setAttribute("stop-opacity",this.fillOpacity1_);

        this.svgStop2_.setAttribute("stop-color",this.fillColour1_);
        if(this.fillColour2_ != null)
            this.svgStop1_.setAttribute("stop-color",this.fillColour2_);
        else if(this.fillOpacity2_ != null)
            this.svgStop1_.setAttribute("stop-color",this.fillColour1_);
           
        this.svgNode_.setAttribute("pointer-events","visibleFill");
        }
}

//Fill opacity 0.0 (transparent) to 1.0 (opaque)
BDCCCircle.prototype.setFillOpacity = function(opacity) {

    this.fillOpacity_ = opacity || 0.3;//save orgiginal for copy
    if (this.fillOpacity_.constructor.toString().indexOf("Array") == -1){
        this.fillOpacity1_ = this.fillOpacity_;
        this.fillOpacity2_ = null;
    }
    else if (this.fillOpacity_.length == 2){
        this.fillOpacity1_ = this.fillOpacity_[0] || 0.1;
        this.fillOpacity2_ = this.fillOpacity_[1] || 0.9;
    }
    else
    {
        this.fillOpacity1_ = this.fillOpacity_[0] || 0.5;
        this.fillOpacity2_ = null;
    }
    
    if(this.usesVml_){
        if(this.fill_){      
            this.vmlCircle_.filled = true;        
            this.vmlFillHelper();
        }
    else
        this.vmlCircle_.filled = false;        
    }
    else{
        this.svgFillHelper();
    }
}
BDCCCircle.prototype.getFillOpacity = function() {
    return this.fillOpacity_;
}

// Fill on/off
BDCCCircle.prototype.setFill = function(fill) {
    this.fill_ = fill;
	this.setFillOpacity(this.fillOpacity_);
}
BDCCCircle.prototype.getFillOpacity = function() {
    return this.fill_;
}

//Event posters
BDCCCircle.prototype.onClick = function(){
    GEvent.trigger(this,"click");
}
BDCCCircle.prototype.onOver = function(){
    GEvent.trigger(this,"mouseover");
}
BDCCCircle.prototype.onOut = function(){
    GEvent.trigger(this,"mouseout");
}

// Creates the DIV representing this circle.
BDCCCircle.prototype.initialize = function(map) {

  //save for later
  this.map_ = map;

  //closures for dom event handlers
  var eClick = GEvent.callback(this,this.onClick);
  var eOver = GEvent.callback(this,this.onOver);
  var eOut = GEvent.callback(this,this.onOut);
  
  //set up invariant details
  if(this.usesVml_){

      try{

      var c = document.createElement("v:oval");
      c.style.position = "absolute";
      var s = document.createElement("v:stroke");
      c.insertBefore(s, null);
			c.stroke = s;
      var f = document.createElement("v:fill");
      c.insertBefore(f, null);
      if(this.tooltip_){
		c.title = this.tooltip_;
		c.style.cursor = "help";
	  }
	map.getPane(G_MAP_MAP_PANE).appendChild(c);
      
      GEvent.clearInstanceListeners(c);//safety 
      GEvent.addDomListener(c,"click",function(event){eClick();});
      GEvent.addDomListener(c,"mouseover",function(){eOver();});
      GEvent.addDomListener(c,"mouseout",function(){eOut();});
      
      this.vmlCircle_ = c;//save for drawing  
      
      }
      catch (ex)
      {
		alert("The designer of this Google Maps web page has attempted to use VML graphics without including the necessary header material.");
      }

  }
  else{


	var svgNS = "http://www.w3.org/2000/svg";

      if (BDCCCircleSvgRoot == null){
		// all the circles go in one SVG element - this makes the mouseover events work properly
		// without one circles bounding box occluding events from a lower z order circle
		BDCCCircleSvgRoot = document.createElementNS(svgNS, "svg");
		map.getPane(G_MAP_MAP_PANE).appendChild(BDCCCircleSvgRoot);
	}

	var svgDefs = document.createElementNS(svgNS, "defs");
	BDCCCircleSvgRoot .appendChild(svgDefs);

	var svgGrad = document.createElementNS(svgNS, "radialGradient");
    svgDefs.appendChild(svgGrad);
    svgGrad.setAttribute("id",this.gradId_);

	var s1 = document.createElementNS(svgNS, "stop");
    s1.setAttribute("offset","0.0");
	var s2 = document.createElementNS(svgNS, "stop");
    s2.setAttribute("offset","1.0");
    svgGrad.appendChild(s1);
    svgGrad.appendChild(s2);

	var svgNode = document.createElementNS(svgNS, "circle");
        if(this.tooltip_ != null){
		svgNode.setAttribute("title",this.tooltip_);
		svgNode.style.cursor = "help";
        } 
	BDCCCircleSvgRoot.appendChild(svgNode);
	
	GEvent.clearInstanceListeners(svgNode);//safety 
	GEvent.addDomListener(svgNode,"click",function(event){eClick();});
	GEvent.addDomListener(svgNode,"mouseover",function(){eOver();});
	GEvent.addDomListener(svgNode,"mouseout",function(){eOut();});

	this.svgNode_ = svgNode;
	this.svgGrad_ = svgGrad;
	this.svgStop1_ = s1;
	this.svgStop2_ = s2;

  }
  
   //set up the appearance of our circle
   this.setStrokeColor(this.lineColour_);
   this.setStrokeOpacity(this.lineOpacity_);
   this.setStrokeWeight(this.lineWidth_);
   this.setFillColor(this.fillColour_);
   this.setFillOpacity(this.fillOpacity_);//does fill too
  
}

// Remove the main DIV from the map pane
BDCCCircle.prototype.remove = function() {

  if (this.svgNode_ != null){
    GEvent.clearInstanceListeners(this.svgNode_);//safety 
    BDCCCircleSvgRoot.removeChild(this.svgNode_);
    this.svgNode_ = null;
  }
  if (this.vmlCircle_ != null){
    GEvent.clearInstanceListeners(this.vmlCircle_);//safety 
    this.map_.getPane(G_MAP_MAP_PANE).removeChild(this.vmlCircle_);
    this.vmlCircle_ = null;    
  }
  
}

// Copy our data to a new BDCCCircle
BDCCCircle.prototype.copy = function() {
  return new BDCCCircle(
      this.point_, 
      this.radiusKm_, 
      this.lineColour_, 
      this.lineWidth_, 
      this.lineOpacity_, 
      this.fill_, 
      this.fillColour_, 
      this.fillOpacity_, 
      this.tooltip_ 
  );
}

// Redraw the circle based on the current projection and zoom level
BDCCCircle.prototype.redraw = function(force) {

  // Calculate the DIV coordinates of the centre point of our circle
  var p = this.map_.fromLatLngToDivPixel(this.point_);
  
  //get the radius
  var sz = this.map_.getSize();
  var bnds = this.map_.getBounds();
  var pxDiag = Math.sqrt((sz.width*sz.width) + (sz.height*sz.height));
  var mDiagKm = bnds.getNorthEast().distanceFrom(bnds.getSouthWest()) / 1000.0;
  var pxPerKm = pxDiag/mDiagKm;

  //get the bounding square to the middle of the line
  var w2 = this.lineWidth_/2.0;
  var rPx = Math.round((this.radiusKm_ * pxPerKm) - w2);
  
  if(this.usesVml_){
  
    this.vmlCircle_.style.display="none";//while drawing or if 0 radius
    if(rPx > 0){
		var hw = rPx * 2;//width and height
		var hw2 = Math.round(hw/2.0);
		var t = p.y - hw2;//top
		var l = p.x - hw2;//left
		this.vmlCircle_.style.width = hw;
		this.vmlCircle_.style.height = hw;
		this.vmlCircle_.style.left = l;
		this.vmlCircle_.style.top = t;
		this.vmlCircle_.style.display="";//finished
		}
  }
  else{
    var rdrh = BDCCCircleSvgRoot.suspendRedraw(10000);//avoid double paint with new centre and then new radius

    this.svgNode_.setAttribute("visibility","hidden");//if 0 radius
    if((rPx > 0)&&(rPx < 3000)){
            var ne = this.map_.fromLatLngToDivPixel(bnds.getNorthEast());
            var sw = this.map_.fromLatLngToDivPixel(bnds.getSouthWest());

		var wd = ne.x-sw.x;
		var ht = sw.y-ne.y;
		var l = sw.x;
		var t = ne.y;

		BDCCCircleSvgRoot.setAttribute("width", wd);
		BDCCCircleSvgRoot.setAttribute("height", ht);
		BDCCCircleSvgRoot.setAttribute("style", "position:absolute; top:"+ t + "px; left:" + l + "px");
		
		var cx = p.x-l;
		var cy = p.y-t;

		this.svgNode_.setAttribute("overflow", "hidden");
		this.svgNode_.setAttribute("r",rPx);
		this.svgNode_.setAttribute("cx",cx);
		this.svgNode_.setAttribute("cy",cy);
		this.svgNode_.setAttribute("visibility","visible");//finished

		
	}
    BDCCCircleSvgRoot.unsuspendRedraw(rdrh);
    BDCCCircleSvgRoot.forceRedraw();
  }

}





