var showinactive=true;
var pntname=new Array();
var pnttime=new Array();
var point=new Array();
var track=new Array();
var poly=new Array();
var markersCnt=0;
var crosshairsSize=19;

GMap2.prototype.addCrosshairs=function() {
    var container=this.getContainer();
    if(this.crosshairs) this.removeCrosshairs();
    var crosshairs=document.createElement("img");
    crosshairs.src='crosshairs.gif';
    crosshairs.style.width=crosshairsSize+'px';
    crosshairs.style.height=crosshairsSize+'px';
    crosshairs.style.border='0';
    crosshairs.style.position='relative';
    crosshairs.style.top=((container.clientHeight-crosshairsSize)/2)+'px';
    crosshairs.style.left=((container.clientWidth-crosshairsSize)/2)+'px';
    crosshairs.style.zIndex='500';
    container.appendChild(crosshairs);
    this.crosshairs=crosshairs;
    return crosshairs;
};


    // ============================================================
    function atanh(x)
    {
        return 0.5*Math.log((1+x)/(1-x));
    }
    function CustomfromLatLngToPixel(lotlan,zoom)
    {
        var PixelsAtZoom = 256*Math.pow(2,zoom);
        var exct = 0.0818197;
        var z = Math.sin(lotlan.latRadians());
        var c = (PixelsAtZoom/(2*Math.PI));
        var x = Math.floor(PixelsAtZoom/2+lotlan.lng()*(PixelsAtZoom/360));
        var y = Math.floor(PixelsAtZoom/2-c*(atanh(z)-exct*atanh(exct*z)));     
        return new GPoint(x,y);
    }
    function CustomfromPixelToLatLng(pixel, zoom)
    {
        var PixelsAtZoom = 256*Math.pow(2,zoom);
        var Lon = ((pixel.x)-PixelsAtZoom/2)/(PixelsAtZoom/360);
        var Lat = ((pixel.y)-PixelsAtZoom/2)/-(PixelsAtZoom/(2*Math.PI));
        Lat = (2*Math.atan(Math.exp(Lat))-Math.PI/2)*180/Math.PI;
        
        var Zu = Lat/(180/Math.PI);
        var Zum1 = Zu+1;
        var exct = 0.0818197;
        var yy = ((pixel.y)-PixelsAtZoom/2);
        var i=100000;
        while ((Math.abs(Zum1-Zu)>0.0000001)&&(i!=0))
        {
            i--;
            Zum1 = Zu;
            Zu = Math.asin(1-((1+Math.sin(Zum1))*Math.pow(1-exct*Math.sin(Zum1),exct))
                /(Math.exp((2*yy)/-(PixelsAtZoom/(2*Math.PI)))*Math.pow(1+exct*Math.sin(Zum1),exct)));
        }
        Lat=Zu*180/Math.PI;
        return new GLatLng(Lat,Lon,false);
    }   
    function CustomGetTileUrl(a,b)
    {
        return "http://sat0"+((a.x+a.y)%5)+".maps.yandex.net/tiles?l=sat&v=1.8.0&x=" + a.x + "&y=" + a.y + "&z=" + b + ".jpg";
    }
    function CustomGetTileUrlHyb(a,b)
    {
        return "http://vec0"+((a.x+a.y)%5)+".maps.yandex.net/tiles?l=skl&v=2.4.2&x=" + a.x + "&y=" + a.y + "&z=" + b + ".png";
    }
    function CustomGetTileUrlMap(a,b)
    {
        return "http://vec.maps.yandex.net/tiles?l=map&v=2.4.2&x=" + a.x + "&y=" + a.y + "&z=" + b + ".png";
    }




  function initialize() {
    if (GBrowserIsCompatible()) {
      map = new GMap2(document.getElementById("map_canvas"));
      map.setCenter(new GLatLng(55.72514, 37.55402), 11);
      map.addControl(new GLargeMapControl());
      map.addMapType(G_SATELLITE_3D_MAP);
//      map.addMapType(G_PHYSICAL_MAP);
      map.addControl(new GScaleControl());

      map.enableScrollWheelZoom(true);
      map.enableContinuousZoom();


            var copyCollection = new GCopyrightCollection('Yandex.Maps');
	    var copyright = new GCopyright(1, new GLatLngBounds(new GLatLng(56.989860, 40.978317), new GLatLng(56.989860, 40.978317)), 0, "Yandex Maps");
            copyCollection.addCopyright(copyright);

            var tilelayers = new Array();
            tilelayers[0] = new GTileLayer(copyCollection, 0, 22 );
            tilelayers[0].getTileUrl = CustomGetTileUrl;

            var GMapTypeOptions = new Object();
            GMapTypeOptions.minResolution = 0;
            GMapTypeOptions.maxResolution = 22;
            GMapTypeOptions.errorMessage = "No map data available";

            var customProjection = new GMercatorProjection(22);
            customProjection.fromLatLngToPixel=CustomfromLatLngToPixel;
            customProjection.fromPixelToLatLng=CustomfromPixelToLatLng;
            var custommap = new GMapType(tilelayers, customProjection, "Я.Спутник", GMapTypeOptions);
            custommap.getTextColor = function() {return "#000000";};
            map.addMapType(custommap);

            tilelayershyb = new GTileLayer(copyCollection, 0, 22 );
            tilelayershyb.getTileUrl = CustomGetTileUrlHyb;
            tilelayershyb.isPng = function() {return true;}; 

            var tilelayers2 = [tilelayers[0],tilelayershyb];
            var custommap2 = new GMapType(tilelayers2, customProjection, "Я.Спутник", {shortName:"YaHybrid"});
            map.addMapType(custommap2);
            var hierarchy = new GHierarchicalMapTypeControl();
            hierarchy.addRelationship(custommap, custommap2, "Я.Гибрид", true);

            map.addControl(hierarchy);



            var copyCollection2 = new GCopyrightCollection('Yandex.Maps');
            var copyright2 = new GCopyright(1, new GLatLngBounds(new GLatLng(56.989860, 40.978317), new GLatLng(56.989860, 40.978317)), 0, "Yandex Maps");
            copyCollection2.addCopyright(copyright2);

            var tilelayers2 = new Array();
            tilelayers2[0] = new GTileLayer(copyCollection2, 0, 22 );
            tilelayers2[0].getTileUrl = CustomGetTileUrlMap;

            var GMapTypeOptions2 = new Object();
            GMapTypeOptions2.minResolution = 0;
            GMapTypeOptions2.maxResolution = 22;
            GMapTypeOptions2.errorMessage = "No map data available";

            var customProjection2 = new GMercatorProjection(22);
            customProjection2.fromLatLngToPixel=CustomfromLatLngToPixel;
            customProjection2.fromPixelToLatLng=CustomfromPixelToLatLng;
            var custommap2 = new GMapType(tilelayers2, customProjection2, "Я.Карта", GMapTypeOptions2);

            custommap.getTextColor = function() {return "#000000";};
            map.addMapType(custommap2);


      map.addControl(new google.maps.LocalSearch(), new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(190,0)));

      GEvent.addListener(map, "dragend", function() {
          document.getElementById('followsl').options.selectedIndex=0;
          document.getElementById('coords').value=map.getCenter().toUrlValue(5);
          document.getElementById('coords').style.background="#ffffff";
        });
      document.getElementById('coords').value=map.getCenter().toUrlValue(5);

      ico_green = new GIcon(G_DEFAULT_ICON);
      ico_green.image="http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png";
      ico_green.iconSize=new GSize(32,32);
      ico_green.shadowSize=new GSize(56,32);
      ico_green.iconAnchor=new GPoint(16,32);
      ico_red = new GIcon(ico_green);
      ico_red.image="http://www.google.com/intl/en_us/mapfiles/ms/micons/red-dot.png";
      ico_yellow = new GIcon(ico_green);
      ico_yellow.image="http://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png";
      ico_blue = new GIcon(ico_green);
      ico_blue.image="http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";

      map.addCrosshairs();

      refreshMap("timer");

    }
  }

  function createMarker(point, ptitle, num, active, fix)
  {
    var marker;
    if(active) {
      marker=new GMarker(point, { icon:(fix?ico_green:ico_yellow), title: ptitle });
    } else {
      marker=new GMarker(point, { icon:ico_red, title: ptitle });
    }
    map.addOverlay(marker);
    GEvent.addListener(marker, "click", function() {
      document.getElementById('followsl').options.selectedIndex=num+2;
      panTo();
    });
  }

  function zeroPad(num,count)
  {
    var numZeropad = num + '';
    while(numZeropad.length < count) {
      numZeropad = "0" + numZeropad; 
    }
    return numZeropad;
  }

  function formatTime(time)
  {
    if(time<0) { time=0; };
    var s=zeroPad(Math.floor(time/3660), 2)+":";
    time=time%3660;
    s+=zeroPad(Math.floor(time/60), 2)+":";
    time=time%60;
    s+=zeroPad(time, 2);
    return s;
  }

  function formatStatusRow(index, name, speed, time, color)
  {
    return '<font color="'+color+'">'+
      "<u><b onClick=\"followsl.options.selectedIndex=" + index + "; panTo();\">" +
      name + "</b></u></td><td>" + speed + " km/h</td><td>"+
      formatTime(time)+" ago</td></font></tr>";
  }

  // Refresh map function
  function refreshMap(x)
  {
    document.getElementById("messages").innerHTML="Refreshing...";
    GDownloadUrl("/perl/GoogleMap.pl?RANDOM=."+Math.random(), function(data, responseCode) {
      if(responseCode == 200) {
        var xml = GXml.parse(data);
        var markers = xml.documentElement.getElementsByTagName("marker");

        map.clearOverlays();
        var statusHTML='<table width="100%" border="0" bgcolor="#999999">';

        for (var i = 0; i < markers.length; i++) {
          point[i] = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
            parseFloat(markers[i].getAttribute("lng")));
          pntname[i]=markers[i].getAttribute("name");
          pnttime[i]=markers[i].getAttribute("time");
          speed=Math.floor(markers[i].getAttribute("speed")*1.852);
          fix=markers[i].getAttribute("fix")*1;
          time = Math.round(new Date().getTime() / 1000.0)-pnttime[i];
          active=true;
          if(time>INACTIVITY) {
            active=false;
          };
          var pnttitle=pntname[i]+" at "+ speed + "km/h ("+(formatTime(time))+" ago, fix="+fix+")";
          followsl=document.getElementById('followsl');

          if((markersCnt!=markers.length) || (x=="resettrack")) {
            track[i]=new Array();
          }

          if(showinactive || active) {
            createMarker(point[i], pnttitle, i, active, fix);
            // Update track
            if((track[i]) && (track[i].length>0)) {
              if(track[i][track[i].length-1].distanceFrom(point[i])>5) {
                if(track[i].length>TRACKLENGTH) {
                  track[i].shift();
                }
                track[i].push(point[i]);
              }
              map.addOverlay(new GPolyline(track[i], "#ff0000", 3));
            } else {
              track[i]=new Array();
              track[i].push(point[i]);
            }

            statusHTML+='<tr bgcolor="#CCDDCC"><td>';
            statusHTML+=formatStatusRow(i+2, pntname[i], speed, time, active?(fix?"green":"yellow"):"red");
          }
        };
        if(markers.length!=followsl.options.length-2) {
          followsl.options.length = 0;
          followsl.options[followsl.options.length] = new Option("None","NONE");
          followsl.options[followsl.options.length] = new Option("All","ALL");
          for (var i = 0; i < markers.length; i++) {
            followsl.options[followsl.options.length] = new Option(pntname[i],i);
          }
          followsl.options.selectedIndex=0;
        }
        markersCnt=markers.length;
        document.getElementById("status").innerHTML=statusHTML;
        panTo();
        document.getElementById("messages").innerHTML="";
      } else {
        document.getElementById("messages").innerHTML="<font color=RED><b>FAILED</b></font>";
      }
    });
    if((timer!=0) && (x=="timer")) {
        window.setTimeout(function(){ refreshMap("timer") }, timer)
    }
  }

  function setTimer(x)
  {
    timer=x;
    refreshMap();
  }

  function toggleInactiveSwitch()
  {
    showinactive=! showinactive;
  }

  function panTo()
  {
      var sb=document.getElementById('followsl');
//      alert(sb.options[sb.options.selectedIndex].value+" "+sb.options.selectedIndex);
      if(sb.options[sb.options.selectedIndex].value!="NONE") {
        if(sb.options[sb.options.selectedIndex].value=="ALL") {
          var bounds = new GLatLngBounds();
          for (var i=0; i< point.length; i++) {
            bounds.extend(point[i]);
          }
          map.setZoom(map.getBoundsZoomLevel(bounds));
          map.setCenter(bounds.getCenter());
        } else {
//          map.setZoom(15);
          map.panTo(point[sb.options.selectedIndex-2]);
        }
        document.getElementById('coords').value=map.getCenter().toUrlValue(5);
        document.getElementById('coords').style.background="#FFFFFF";
      }
  }


