$(document).bind('unload', GUnload);
var map, map_zoom, map_bounds, map_icon = [], map_points = [];
map_icon[null] = new GIcon(G_DEFAULT_ICON); map_icon[null].shadow = null; map_icon[null].iconSize = new GSize(32, 32); map_icon[null].iconAnchor = new GPoint(16, 16); map_icon[null].infoWindowAnchor = new GPoint(16, 16);
function map_load(fixed, max_zoom)
{
  if (document.getElementById('map') == null) return;
  if (typeof (fixed) == 'undefined') fixed = false;
  map_zoom = (typeof (max_zoom) == 'undefined') ? 99 : max_zoom;
  if (GBrowserIsCompatible())
  {
    map = new GMap2(document.getElementById('map'));
    if (fixed)
    {
      map.disableDoubleClickZoom();
      map.disableDragging();
    }
    else
    {
      map.enableDoubleClickZoom();
      map.addControl(new GSmallZoomControl3D());
    }
    map.disableContinuousZoom();
    map_bounds = new GLatLngBounds();
  }
}
function map_resize(shrink)
{
  if (typeof (shrink) == 'undefined') shrink = 0;
  var point = null;
  if (map_points.length > 0)
  {
    point = map_points[0];
    if ((shrink == 0) || (map_points.length < 10))
    {
      for (var i = 0; i < map_points.length; i++) map_bounds.extend(map_points[i]);
      map_points = [];
    }
    else
    {
      var lats = [], lngs = [];
      for (var i = 0; i < map_points.length; i++)
      {
        lats.push(map_points[i].lat());
        lngs.push(map_points[i].lng());
      }
      lats.sort(); lngs.sort();
      map_points = [];
      shrink = Math.ceil(lats.length * shrink);
      map_bounds.extend(new GLatLng(lats[shrink], lngs[shrink]));
      map_bounds.extend(new GLatLng(lats[lats.length - shrink - 1], lngs[lngs.length - shrink - 1]));
    }
  }
  var zoom = map.getBoundsZoomLevel(map_bounds);
  if (zoom > map_zoom) zoom = map_zoom;
  map.setCenter(map_bounds.getCenter(), zoom);
  if ((document.getElementById('pan') != null) && (point != null))
  {
    var sv = new GStreetviewClient();
    sv.getNearestPanorama(point, function(data)
    {
      if (data.code == 200)
      {
        var angle = map_angle(point, data.location.latlng);
        new GStreetviewPanorama(document.getElementById('pan'), { latlng: data.location.latlng, pov: { yaw: angle} })
      }
    });
  }
}
function map_angle(endLatLng, startLatLng)
{
  var DEGREE_PER_RADIAN = 57.2957795;
  var RADIAN_PER_DEGREE = 0.017453;
  var dlat = endLatLng.lat() - startLatLng.lat();
  var dlng = endLatLng.lng() - startLatLng.lng();
  var yaw = Math.atan2(dlng * Math.cos(endLatLng.lat() * RADIAN_PER_DEGREE), dlat) * DEGREE_PER_RADIAN;
  return map_angle_wrap(yaw);
}
function map_angle_wrap(angle)
{
  if (angle >= 360) angle -= 360; else if (angle < 0) angle += 360;
  return angle;
}
function map_point(point, info, icon)
{
  if ((typeof (icon) == 'undefined') || (icon == null)) icon = map_icon[null];
  var marker = new GMarker(point, icon, (info == null));
  if (info != null) marker.bindInfoWindowHtml(info, { maxWidth: 300 });
  map.addOverlay(marker);
  map_points.push(point);
}
function map_polyline(start, stop, encoded, info)
{
  var polyline;
  if (encoded == '') polyline = new GPolyline([start, stop], '#0000ff', 5, 0.5);
  else
  {
    var encoded_parts = encoded.split(',');
    polyline = GPolyline.fromEncoded({ color: '#0000ff', weight: 5, opacity: 0.5, points: encoded_parts[0], zoomFactor: 32, levels: encoded_parts[1], numLevels: 4 });
  }
  map_bounds.extend(polyline.getBounds().getNorthEast());
  map_bounds.extend(polyline.getBounds().getSouthWest());
  map.addOverlay(polyline);
  if (map_icon['start'] == null) map_icon['start'] = new GIcon(map_icon[null], 'http://maps.google.com/mapfiles/kml/pal4/icon54.png');
  if (map_icon['stop'] == null) map_icon['stop'] = new GIcon(map_icon[null], 'http://maps.google.com/mapfiles/kml/pal4/icon7.png');
  var marker_start = new GMarker(start, map_icon['start'], (info == null));
  if (info != null) marker_start.bindInfoWindowHtml(info, { maxWidth: 300 });
  map.addOverlay(marker_start);
  var marker_stop = new GMarker(stop, map_icon['stop'], (info == null));
  if (info != null) marker_stop.bindInfoWindowHtml(info, { maxWidth: 300 });
  map.addOverlay(marker_stop);
}
function map_directions(lat, lng, lat2, lng2, callback)
{
  var dir = new GDirections();
  GEvent.addListener(dir, 'load',
    function()
    {
      var p = dir.getPolyline();
      var q = null, r = null;
      for (var i in p)
      {
        if (p[i] == null) continue;
        else if (typeof (p[i]) == 'object')
        {
          if (p[i].length)
          {
            if (p[i].length > 0)
            {
              if (p[i][0].x)
              {
                q = p[i];
                continue;
              }
              else if (p[i][0] < 32)
              {
                r = p[i];
                continue;
              }
            }
          }
        }
      }
      if ((q == null) || (r == null))
      {
        callback('');
        return;
      }
      var points = [];
      for (var i = 0; i < q.length; i++) points.push({ Latitude: q[i].y, Longitude: q[i].x, Level: r[i] });
      map_encode(points, callback);
    });
  GEvent.addListener(dir, 'error', function() { callback(''); });
  dir.load('from:' + lat + ',' + lng + ' to:' + lat2 + ',' + lng2, { getPolyline: true });
}
function map_encode(points, callback)
{
  var plat = 0, plng = 0;
  var encoded_points = '', encoded_levels = '';
  for (var i = 0; i < points.length; ++i)
  {
    var point = points[i];
    var lat = point.Latitude;
    var lng = point.Longitude;
    var level = point.Level;
    var late5 = Math.floor(lat * 1e5);
    var lnge5 = Math.floor(lng * 1e5);
    dlat = late5 - plat;
    dlng = lnge5 - plng;
    plat = late5;
    plng = lnge5;
    encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
    encoded_levels += encodeNumber(level);
  }
  callback(encoded_points + ',' + encoded_levels);
}
function encodeSignedNumber(num)
{
  var sgn_num = num << 1;
  if (num < 0) sgn_num = ~(sgn_num);
  return (encodeNumber(sgn_num));
}
function encodeNumber(num)
{
  var encodeString = "";
  while (num >= 0x20)
  {
    encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
    num >>= 5;
  }
  encodeString += (String.fromCharCode(num + 63));
  return encodeString;
}