var geocoder = null;
var Gselected_company_id='';
var wait_for_address=1;

var anchor_lats=new Array();
var anchor_longs=new Array();
var selected_zoom=15;

	
function oparate_cords(marker_id,lat,lng)
{
	nodes = $A(anchor_lats);	
	nodes.each(function(node,index){ if (node[1]==marker_id) {node[0]=lat;anchor_longs[index]=new Array(lng,marker_id);} });
	//alert(nodes.inspect());
}

function operate_address(map,marker_id,lat,lng,address,text,icon_src,icon_width,icon_height,draggable)
{
	if (geocoder) {
        geocoder.getLatLng(
          address,
          function(point) {
            if (!point) {
              alert(address + " not found");
			  insert_marker(map,marker_id,lat,lng,text,icon_src,icon_width,icon_height,draggable)  	
			  return '';
            } else {
              map.setCenter(point, 15);
			  return insert_marker(map,marker_id,point.lat(),point.lng(),text,icon_src,icon_width,icon_height,draggable);  		  
            }
          }
        );
      }
}

function insert_marker(map,marker_id,lat,lng,text,icon_src,icon_width,icon_height,draggable) 
{
	var blueIcon = new GIcon(G_DEFAULT_ICON);
	if (icon_src!='')
	{		
		blueIcon.image = icon_src;
		blueIcon.printImage = icon_src;			
		blueIcon.iconSize = new GSize(icon_width,icon_height);
		blueIcon.iconAnchor = new GPoint(icon_width/2,icon_height);
		blueIcon.shadowSize = new GSize(0, 0);
		blueIcon.infoWindowAnchor = new GPoint(icon_width/2, 0);
		blueIcon.imageMap = [0,0,icon_width,0,icon_width,icon_height,0,icon_height];	//for clickable area	
	}
	var marker = new GMarker(new GLatLng(lat,lng)/*, {icon:blueIcon}*/);
	if (draggable==1)
	{
			marker = new GMarker(new GLatLng(lat,lng), {draggable: true/*, icon:blueIcon*/});
			GEvent.addListener(marker, "dragstart", function() {
			  map.closeInfoWindow();
			});
			GEvent.addListener(marker, "dragend", function() {
			  var rez = marker.getLatLng();
			  oparate_cords(marker_id,rez.lat(),rez.lng());
			});	 
	}
	if (text!='')
	{
		GEvent.addListener(marker,"mouseover", function() {load_info_window(marker,text)});	
		//GEvent.addListener(marker,"mouseout", function() {marker.closeInfoWindow();});	
	}
	map.addOverlay(marker);	
	map.setCenter(new GLatLng(lat, lng), selected_zoom);
	
	return marker;		
}

function createMarker(map,marker_id,lat,lng,address,text,icon_src,icon_width,icon_height,draggable) 
{	 
	if (address!='') return operate_address(map,marker_id,lat,lng,address,text,icon_src,icon_width,icon_height,draggable);	
	else return insert_marker(map,marker_id,lat,lng,text,icon_src,icon_width,icon_height,draggable); 	
}

function redrawPolyline(map,polyline,markers){ 
	 if (polyline) { map.removeOverlay(polyline); }
	 
	 var new_polyline = new GPolyline([], '#ff0000', 4, 0.7); 
     map.addOverlay(new_polyline);
	 
	 for (var i = 0; i < markers.length; i++) {
	 		new_polyline.insertVertex(i+1, markers[i].marker_point); 		
	}
			alert('jj');
	map.setCenter(new_polyline.getBounds().getCenter());
	map.setZoom(map.getBoundsZoomLevel(new_polyline.getBounds())); alert(map.getBoundsZoomLevel(new_polyline.getBounds()));
	
	return new_polyline;
}
	
function MyApplication(id, start_x, start_y, zoom)
{
	var map;
    if (GBrowserIsCompatible())
    {
    	map = new GMap2(document.getElementById("map_canvas_"+id));
	    map.setCenter(new GLatLng(start_x, start_y), zoom);
	    map.addControl(new GSmallMapControl()); //arrows lef-right
		map.addControl(new GMapTypeControl()); // view mode (satelite...)
		//map.addControl(new GLargeMapControl()); //left side zooming tool
		geocoder = new GClientGeocoder();	
  	}
  	return map;
}

function initialize_googleMaps(id, start_x, start_y, zoom)
{
  var map = MyApplication(id, start_x, start_y, zoom);
  selected_zoom = zoom;
  return map;
}


function showAddress(map,address) {  
  if (geocoder) {
	geocoder.getLatLng(
	  address,
	  function(point) {
		if (!point) {
		  alert(address + " not found");
		} else {
		  map.setCenter(point, 15);
		  var marker = new GMarker(point);
		  map.addOverlay(marker);
		  marker.openInfoWindowHtml(address);
		}
	  }
	);
  }
}


function load_info_window(marker,id)
{
	$.ajax({
		   type: "POST",
		   url: "jax/load_info_window.jax.php",
		   data: {'id':id},
		   success: function(msg){			
		   		marker.openInfoWindowHtml(msg);
		   }
		 });	
}


/* route simulation */
var step = 100; // metres
var tick = 100; // milliseconds
var poly;
var poly2;
var lastVertex = 0;
var eol;
var marker;
var k=0;
var stepnum=0;
var speed = "";
var saved_d="";
var pause=0;
var segment_index=0;
var saved_map='';
var saved_markers=new Array();

function updatePoly(d) {
	// Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow
	if (poly2.getVertexCount() > 20) {
	  poly2=new GPolyline([poly.getVertex(lastVertex-1)]);
	  saved_map.addOverlay(poly2)
	}

	if (poly.GetIndexAtDistance(d) < lastVertex+2) {
	   if (poly2.getVertexCount()>1) {
		 poly2.deleteVertex(poly2.getVertexCount()-1)
	   }
	   poly2.insertVertex(poly2.getVertexCount(),poly.GetPointAtDistance(d));
	} else {
	  poly2.insertVertex(poly2.getVertexCount(),poly.getVertex(lastVertex++));
	}
  }
	
function animate(d) {
	saved_d=d;
	if (d>eol) {
	  //console.dir("Trip completed");
	  //console.dir("Miles: "+(d/1609.344).toFixed(2));
	  if (segment_index<saved_markers.length-2) {segment_index++;getNextRouteSegment();}
	  return;
	}
	var p = poly.GetPointAtDistance(d);
	if (k++>=800/step) {
	  saved_map.panTo(p);
	  k=0;
	}
	
	marker.setPoint(p);				
	updatePoly(d);				
	if (!pause) setTimeout("animate("+(d+step)+")", tick);

}

function getNextRouteSegment()
{
	lastVertex = 0;
	k=0;
	stepnum=0;
	
	var tmp_poly = new GPolyline([saved_markers[segment_index].marker_point,saved_markers[segment_index+1].marker_point]);				
	pause=0		
	poly=tmp_poly;
	eol=poly.Distance();
	
	//saved_map.addOverlay(new GMarker(poly.getVertex(0),G_START_ICON));
	//saved_map.addOverlay(new GMarker(poly.getVertex(poly.getVertexCount()-1),G_END_ICON));
	
	poly2 = new GPolyline([poly.getVertex(0)]);
	saved_map.addOverlay(poly2);
	//saved_markers[segment_index].marker_point.openInfoWindowHtml('test');
	if (saved_markers[segment_index].marker_anchor!='') load_info_window(saved_markers[segment_index].marker_anchor,saved_markers[segment_index].id);
	animate(0);
	
}

function init_anim(map,markers)
{
	saved_d="";
	saved_map=map;
	saved_markers=markers;
	
	var car = new GIcon();
	car.image="admin/imgs/default/icons/caricon.png"
	car.iconSize=new GSize(29,29);
	car.iconAnchor=new GPoint(16,9);
	
	marker = new GMarker(saved_markers[0].marker_point,{icon:car});
	saved_map.addOverlay(marker);
	saved_map.setCenter(saved_markers[0].marker_point,13);
	getNextRouteSegment();
}
function pause_anim()
{
	if (pause==0) pause=1; else {pause=0;animate(saved_d);}
}







/*********************************************************************\
*                                                                     *
* epolys.js                                          by Mike Williams *
*                                                                     *
* A Google Maps API Extension                                         *
*                                                                     *
* Adds various Methods to GPolygon and GPolyline                      *
*                                                                     *
* .Contains(latlng) returns true is the poly contains the specified   *
*                   GLatLng                                           *
*                                                                     *
* .Area()           returns the approximate area of a poly that is    *
*                   not self-intersecting                             *
*                                                                     *
* .Distance()       returns the length of the poly path               *
*                                                                     *
* .Bounds()         returns a GLatLngBounds that bounds the poly      *
*                                                                     *
* .GetPointAtDistance() returns a GLatLng at the specified distance   *
*                   along the path.                                   *
*                   The distance is specified in metres               *
*                   Reurns null if the path is shorter than that      *
*                                                                     *
* .GetPointsAtDistance() returns an array of GLatLngs at the          *
*                   specified interval along the path.                *
*                   The distance is specified in metres               *
*                                                                     *
* .GetIndexAtDistance() returns the vertex number at the specified    *
*                   distance along the path.                          *
*                   The distance is specified in metres               *
*                   Reurns null if the path is shorter than that      *
*                                                                     *
* .Bearing(v1?,v2?) returns the bearing between two vertices          *
*                   if v1 is null, returns bearing from first to last *
*                   if v2 is null, returns bearing from v1 to next    *
*                                                                     *
*                                                                     *
***********************************************************************
*                                                                     *
*   This Javascript is provided by Mike Williams                      *
*   Community Church Javascript Team                                  *
*   http://www.bisphamchurch.org.uk/                                  *
*   http://econym.org.uk/gmap/                                        *
*                                                                     *
*   This work is licenced under a Creative Commons Licence            *
*   http://creativecommons.org/licenses/by/2.0/uk/                    *
*                                                                     *
***********************************************************************
*                                                                     *
* Version 1.1       6-Jun-2007                                        *
* Version 1.2       1-Jul-2007 - fix: Bounds was omitting vertex zero *
*                                add: Bearing                         *
* Version 1.3       28-Nov-2008  add: GetPointsAtDistance()           *
* Version 1.4       12-Jan-2009  fix: GetPointsAtDistance()           *
*                                                                     *
\*********************************************************************/


// === A method for testing if a point is inside a polygon
// === Returns true if poly contains point
// === Algorithm shamelessly stolen from http://alienryderflex.com/polygon/ 
GPolygon.prototype.Contains = function(point) {
  var j=0;
  var oddNodes = false;
  var x = point.lng();
  var y = point.lat();
  for (var i=0; i < this.getVertexCount(); i++) {
    j++;
    if (j == this.getVertexCount()) {j = 0;}
    if (((this.getVertex(i).lat() < y) && (this.getVertex(j).lat() >= y))
    || ((this.getVertex(j).lat() < y) && (this.getVertex(i).lat() >= y))) {
      if ( this.getVertex(i).lng() + (y - this.getVertex(i).lat())
      /  (this.getVertex(j).lat()-this.getVertex(i).lat())
      *  (this.getVertex(j).lng() - this.getVertex(i).lng())<x ) {
        oddNodes = !oddNodes
      }
    }
  }
  return oddNodes;
}

// === A method which returns the approximate area of a non-intersecting polygon in square metres ===
// === It doesn't fully account for spechical geometry, so will be inaccurate for large polygons ===
// === The polygon must not intersect itself ===
GPolygon.prototype.Area = function() {
  var a = 0;
  var j = 0;
  var b = this.Bounds();
  var x0 = b.getSouthWest().lng();
  var y0 = b.getSouthWest().lat();
  for (var i=0; i < this.getVertexCount(); i++) {
    j++;
    if (j == this.getVertexCount()) {j = 0;}
    var x1 = this.getVertex(i).distanceFrom(new GLatLng(this.getVertex(i).lat(),x0));
    var x2 = this.getVertex(j).distanceFrom(new GLatLng(this.getVertex(j).lat(),x0));
    var y1 = this.getVertex(i).distanceFrom(new GLatLng(y0,this.getVertex(i).lng()));
    var y2 = this.getVertex(j).distanceFrom(new GLatLng(y0,this.getVertex(j).lng()));
    a += x1*y2 - x2*y1;
  }
  return Math.abs(a * 0.5);
}

// === A method which returns the length of a path in metres ===
GPolygon.prototype.Distance = function() {
  var dist = 0;
  for (var i=1; i < this.getVertexCount(); i++) {
    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
  }
  return dist;
}

// === A method which returns the bounds as a GLatLngBounds ===
GPolygon.prototype.Bounds = function() {
  var bounds = new GLatLngBounds();
  for (var i=0; i < this.getVertexCount(); i++) {
    bounds.extend(this.getVertex(i));
  }
  return bounds;
}

// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
GPolygon.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getVertex(0);
  if (metres < 0) return null;
  var dist=0;
  var olddist=0;
  for (var i=1; (i < this.getVertexCount() && dist < metres); i++) {
    olddist = dist;
    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
  }
  if (dist < metres) {return null;}
  var p1= this.getVertex(i-2);
  var p2= this.getVertex(i-1);
  var m = (metres-olddist)/(dist-olddist);
  return new GLatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m);
}

// === A method which returns an array of GLatLngs of points a given interval along the path ===
GPolygon.prototype.GetPointsAtDistance = function(metres) {
  var next = metres;
  var points = [];
  // some awkward special cases
  if (metres <= 0) return points;
  var dist=0;
  var olddist=0;
  for (var i=1; (i < this.getVertexCount()); i++) {
    olddist = dist;
    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
    while (dist > next) {
      var p1= this.getVertex(i-1);
      var p2= this.getVertex(i);
      var m = (next-olddist)/(dist-olddist);
      points.push(new GLatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m));
      next += metres;    
    }
  }
  return points;
}

// === A method which returns the Vertex number at a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
GPolygon.prototype.GetIndexAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getVertex(0);
  if (metres < 0) return null;
  var dist=0;
  var olddist=0;
  for (var i=1; (i < this.getVertexCount() && dist < metres); i++) {
    olddist = dist;
    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
  }
  if (dist < metres) {return null;}
  return i;
}

// === A function which returns the bearing between two vertices in decgrees from 0 to 360===
// === If v1 is null, it returns the bearing between the first and last vertex ===
// === If v1 is present but v2 is null, returns the bearing from v1 to the next vertex ===
// === If either vertex is out of range, returns void ===
GPolygon.prototype.Bearing = function(v1,v2) {
  if (v1 == null) {
    v1 = 0;
    v2 = this.getVertexCount()-1;
  } else if (v2 ==  null) {
    v2 = v1+1;
  }
  if ((v1 < 0) || (v1 >= this.getVertexCount()) || (v2 < 0) || (v2 >= this.getVertexCount())) {
    return;
  }
  var from = this.getVertex(v1);
  var to = this.getVertex(v2);
  if (from.equals(to)) {
    return 0;
  }
  var lat1 = from.latRadians();
  var lon1 = from.lngRadians();
  var lat2 = to.latRadians();
  var lon2 = to.lngRadians();
  var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
  if ( angle < 0.0 ) angle  += Math.PI * 2.0;
  angle = angle * 180.0 / Math.PI;
  return parseFloat(angle.toFixed(1));
}




// === Copy all the above functions to GPolyline ===
GPolyline.prototype.Contains             = GPolygon.prototype.Contains;
GPolyline.prototype.Area                 = GPolygon.prototype.Area;
GPolyline.prototype.Distance             = GPolygon.prototype.Distance;
GPolyline.prototype.Bounds               = GPolygon.prototype.Bounds;
GPolyline.prototype.GetPointAtDistance   = GPolygon.prototype.GetPointAtDistance;
GPolyline.prototype.GetPointsAtDistance  = GPolygon.prototype.GetPointsAtDistance;
GPolyline.prototype.GetIndexAtDistance   = GPolygon.prototype.GetIndexAtDistance;
GPolyline.prototype.Bearing              = GPolygon.prototype.Bearing;


 
