var config = new Object();
var texts = new Object();
var dealers = new Object();

var selectedCountry = '';
var selectedState = '';
var selectedCity = '';

var cityLatLng = '';
var zipLatLng = '';

var startZoomlevel =   3; // Zoom on map load
var countryZoomlevel = 4; // Zoom after country select
var stateZoomlevel =   6; // Zoom after state select
var cityZoomlevel =    8; // Zoom after city select
var zipZoomlevel =     8; // Zoom after zip search
var dealerZoomlevel = -1; // Zoom after clicking dealer marker (not used)
var markerZoomlevel =  7; // Markers visible after this zoomlevel

var gm_map = '';
var gm_gd  = '';
var gm_gc  = '';
var gm_mgr = '';

var dealerlistUpdateTimer = false;
var skipDealerlistUpdate = false;
  
  
$(document).ready( function () {

  // Set map opacity lower while loading
  $("#dealer_form, #dealer_map").css("opacity", 0.2);
  
  // Configuration
  config.mapLanguage = $("#mapLanguage").text();
  config.selectedCountry = $("#selectedCountry").text();
  // config.dealerType = $("#dealerType").text();
  
  // Translations
  // texts.showOnMap = $("#showOnMap").text();
  texts.phonePrefix = $("#phonePrefix").text();
  texts.faxPrefix = $("#faxPrefix").text();
  texts.showDirectionsFrom = $("#showDirectionsFrom").text();
  texts.addressCity = $("#addressCity").text();
  texts.showButton = $("#showButton").text();
  
  // Map
  gm_map = new GMap2( document.getElementById("dealer_map") );
  gm_map.setCenter(new GLatLng(44.4651510, -94.3066406), startZoomlevel);
  gm_map.enableScrollWheelZoom();
  gm_map.addControl(new GSmallMapControl());
  gm_map.addControl(new GOverviewMapControl());
  // gm_map.addControl(new GMapTypeControl());  
  
  // Map addons
  var gm_mgrOptions = new Object({borderPadding: 100});
  gm_mgr = new MarkerManager(gm_map, gm_mgrOptions);
  gm_gc = new GClientGeocoder();
  // gm_gd = new GDirections(map, document.getElementById("directions"));
  
  // Map events
  GEvent.addListener(gm_map, "moveend", function () {
    if (!skipDealerlistUpdate && gm_map.getZoom() >= markerZoomlevel) {
      $("#dealer_list").hide();
      $("#dealers_loading").show();
      clearTimeout(dealerlistUpdateTimer);
      dealerlistUpdateTimer = setTimeout( function () { 
        updateDealerlist();
        $("#dealers_loading").hide();
        $("#dealer_list").show();
      }, 3000);
    }
    skipDealerlistUpdate = false;
  });
  
  /*
  GEvent.addListener(gm_map, "zoomend", function () { });
  GEvent.addListener(gm_map, "dragend", function () { });
  GEvent.addListener(gm_map, "addoverlay", function (overlay) {});
  GEvent.addListener(gm_map, "click", function (overlay, point) { if (point != undefined) alert(point); });
  */
  
  //
  // Dealer form
  //

  // Use predefined country
  if (config.selectedCountry) selectedCountry = config.selectedCountry;
  
  // Get dealer countries
  getDealerLocations();
   
  // Country-select
  $("#dealermap .country").change( function () {
    selectedCountry = $(this).val();
    if (!selectedCountry) return false;
    
    selectedState = '';
    selectedCity = '';
    cityLatLng = '';
    
    getDealerLocations();
  
    // Focus on country
    skipDealerlistUpdate = true;
    gm_gc.getLatLng(selectedCountry, function (gLatLng) {
      gm_map.setCenter(gLatLng, countryZoomlevel);
    });
  
    // Enable state-select
    $(".state").removeAttr("disabled");
    $('.state option:first').text(selectedCountry=='Canada'?'Select province':'Select state');
  });
  
  
  // State-select
  $("#dealermap .state").change( function () {
    selectedState = $(this).val();
    if (!selectedState) return false;
    
    selectedCity = '';
    cityLatLng = '';
    
    getDealerLocations();
  
    // Focus on state
    skipDealerlistUpdate = true;
    gm_gc.getLatLng(selectedState +", "+ selectedCountry, function (gLatLng) {
      gm_map.setCenter(gLatLng, stateZoomlevel);
    });
  
    // Enable city-select
    $(".city").removeAttr("disabled");
  });
  
   
  // City-select
  $("#dealermap .city").change( function () {
    selectedCity = $(this).val();
    if (!selectedCity) return false;
    
    // Focus on city
    gm_gc.getLatLng(selectedCity +", "+ selectedState, function (gLatLng) {
      gm_map.setCenter(gLatLng, cityZoomlevel);
      cityLatLng = gLatLng;
    });
  });
  
  
  // Zip search
  $("#zipsearch").submit( function (e) {
    selectedCountry = '';
    selectedState = '';
    selectedCity = '';
    cityLatLng = '';
    
    $("#dealermap").find(".country, .state, .city").find("option").removeAttr("selected");
    var zip = $(this).find(".zip").val();
    var zipAddress = zip +", "+ (selectedCountry ? ", "+ selectedCountry : "USA");
    gm_gc.getLatLng(zipAddress, function (gLatLng) {
      gm_map.setCenter(gLatLng, zipZoomlevel);
      zipLatLng = gLatLng;
    });
    e.preventDefault();
  });
  
    
  //
  // Dealer markers
  //
    
  // Get all dealers & create markers
  getDealers();
  createDealerMarkers();
  
  // All completed; hide loading -message, set opacity of map to 1
  $("#map_loading").hide();
  $("#dealer_form, #dealer_map").css("opacity", 1.0);
});


// Loads all dealers from CSV-file, 
// add to dealers-array as objects
function getDealers () {
  
  $.ajax({
    type:  "GET",
    async: false,
    cache: true,
    url:   "/dealers.csv",
    data:  '',
    dataType: 'text',
    success: function (data) {
      var dataLines = data.split("\n");
      for (i = 0; i < dataLines.length; i++) {
        var line = dataLines[i].split(";;;");
        var pid = line[0];
        if (pid) {
          var dealer = new Object({
            "pid":             pid,
            "id":              line[1],
            "name":            line[2],
            "address":         line[3],
            "address2":        line[4],
            "zip":             line[5],
            "city":            line[6],
            "state":           line[7],
            "country":         line[8],
            "phone":           line[9],
            "fax":             line[10],
            "email":           line[11],
            "website":         line[12],
            "coordinates_lat": line[13],
            "coordinates_lng": line[14]
          });
          dealers[ pid ] = dealer;
        }
      }
    },
    complete: function () {
    }
  });
}


// Creates and adds all dealer markers to Markermanager
function createDealerMarkers () {
  var dealerMarkers = new Array();
  $.each(dealers, function (pid, dealer) {
    if (dealer.coordinates_lat && dealer.coordinates_lng) {
      dealers[ pid ].marker = createDealerMarker(pid, new GLatLng(dealer.coordinates_lat, dealer.coordinates_lng));
      dealerMarkers.push(dealers[ pid ].marker);
    }
  });
  
  gm_mgr.addMarkers(dealerMarkers, markerZoomlevel);
  gm_mgr.refresh();
  dealerMarkers = new Array();
}


// Loads all distinct countries, states and cities from 
// dealer database for dropdown based browsing
function getDealerLocations () {

  // Reset zip search
  $("#zipsearch .zip").val("");
  zipLatLng = '';
  
  var params = new Object();
  if (selectedCountry)   params['country'] = selectedCountry;
  if (selectedState)     params['state'] = selectedState;
  if (selectedCity)      params['city'] = selectedCity; 
  // if (config.dealerType) params['type'] = config.dealerType;
  
  $.get("/dealer_locations.xml", params, function (data) {
  
    var countryOptions = '';
    var stateOptions = '';
    var cityOptions = '';
  
    // Countries
    if (!selectedCountry) {
      $("country", data).each( function () {
        var country = $(this).text();
        countryOptions += '<option value="'+ country +'">'+ country +'</option>';
      });
      // Select first option
      $(".country option:eq(0)").attr("selected", "selected");
    }
    
    // States
    if (selectedCountry && !selectedState) {
      $(".state optgroup option").remove();
      $("state", data).each( function () {
        var state = $(this).text();
        stateOptions += '<option value="'+ state +'">'+ state +'</option>';
      });
      
      // Select first option
      $(".state option:eq(0)").attr("selected", "selected");
    }
    
    // Cities
    if (selectedCountry && selectedState) {
      $(".city optgroup option").remove();
      $("city", data).each( function () {
        var city = $(this).text();
        cityOptions += '<option value="'+ city +'">'+ city +'</option>';
      });
      
      // Select first option
      $(".city option:eq(0)").attr("selected", "selected");
    }
    
    // Append country/state/city options to selects, select first option
    if (countryOptions) {
      $(".country optgroup").append(countryOptions);
      $(".country option:eq(0)").attr("selected", "selected");
    }
    
    if (stateOptions) {
      $(".state optgroup").append(stateOptions);
      $(".state option:eq(0)").attr("selected", "selected");
    }
    
    if (cityOptions) {
      $(".city optgroup").append(cityOptions);
      $(".city option:eq(0)").attr("selected", "selected");
    }
  });
}

// Updates the dealer list under map
function updateDealerlist () {

  // Remove previous dealers
  $("#dealer_list").empty();
  
  var dealersVisible = new Array();
  var bounds = gm_map.getBounds();
  $.each(dealers, function (pid, dealer) {
    // Dealer has marker, is in bounds of map and isn't hidden (map zoomlevel equal or lower)
    if (dealer.marker && bounds.containsLatLng(dealer.marker.getLatLng()) && !dealer.marker.isHidden())
      dealersVisible.push(dealer);
  });
  
  // Sort by distance
  if (zipLatLng || cityLatLng)
    dealersVisible.sort( sortDealersByDistance );

  // Append HTML
  $.each(dealersVisible, function () {
    var dealer = this;
    $(document.createElement("div"))
      .addClass("dealer")
      .html( createDealerHtml(dealer.pid) )
      .click( function () { showDealer(dealer.pid) } )
      .appendTo("#dealer_list")
      .hover(
        function () { $(this).addClass("hover") },
        function () { $(this).removeClass("hover") }
      );
  });
  
  dealersVisible = new Array();
}

function sortDealersByDistance (a, b) {
  var x = sprintf("%04d", calculateDealerDistance(a.pid));
  var y = sprintf("%04d", calculateDealerDistance(b.pid));
  return ((x < y) ? -1 : ((x > y) ? 1 : 0))
}


function createDealerMarker (pid, gLatLng) {
  var dealer = dealers[ pid ];
  if (!gLatLng) return false;
  var marker = new GMarker(
    gLatLng,
    new Object({title: dealer.name})
  );
  GEvent.addListener(marker, "click", function () { this.openInfoWindow( createDealerHtml(pid) + createDirectionHtml(pid) ) });
  GEvent.addListener(marker, "remove", function () { this.hide() }); // Hide marker if Markermanager removes it
  return marker;
}


function createDealerHtml (pid) {
  var dealer = dealers[ pid ];
  if (!dealer) return false;
  var html = 
    "<b>"+ dealer.name +"</b><br />"+
    dealer.address +"<br />"+
    (dealer.address2 ? dealer.address2 +"<br />" : "") +
    dealer.zip +" "+ dealer.city +", "+ dealer.state +"<br />"+
    (dealer.phone ? texts.phonePrefix + dealer.phone +"<br />" : "") +
    (dealer.fax ? texts.faxPrefix + dealer.fax +"<br />" : "") +
    (dealer.website ? '<a href="http://'+ dealer.website +'">'+ dealer.website +'</a><br />' : "") +
    (dealer.email ? '<a href="mailto:'+ dealer.email +'">'+ dealer.email +'</a><br />' : "") +
    (zipLatLng || cityLatLng ? 'Distance: '+ calculateDealerDistance(pid) +' miles<br />' : "") +
    "";
  return html;
}


function calculateDealerDistance (pid) {
  var dealer = dealers[ pid ];
  if (!dealer || !zipLatLng && !cityLatLng) return false;
  
  var dealerLatLng = dealer.marker.getLatLng();
  var lat1 = dealerLatLng.lat();
  var lon1 = dealerLatLng.lng();
  
  var latLng = '';
  if (cityLatLng) latLng = cityLatLng;
  if (zipLatLng) latLng = zipLatLng; 
  var lat2 = latLng.lat();
  var lon2 = latLng.lng();
  
  var R = 6371;
  var dLat = (lat2 - lat1).toRad();
  var dLon = (lon2 - lon1).toRad(); 
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
          Math.sin(dLon/2) * Math.sin(dLon/2); 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c;
  return parseInt(d / 1.609344);
}


function showDealer (pid) {
  var dealer = dealers[ pid ];
  if (!dealer) return false;
  GEvent.trigger(dealer.marker, "click");
  $.scrollTo("#dealermap");
}


function createDirectionHtml (pid) {
  var html = 
    '<br />'+
    texts.showDirectionsFrom +
    '<form method="get" class="directions" id="directions_'+ pid +'" name="directions_'+ pid +'" onsubmit="showDirections('+ pid +', this); return false" action="#">'+
    '<input type="text" name="from" class="from" value="" />'+
    '<input type="submit" name="submit" class="show" value="'+ texts.showButton +'" /><br />'+
    texts.addressCity +
    '</form>';
  return html;
}


function showDirections (pid, form) {
  var dealer = dealers[ pid ];
  var from = $(form).find("input[@name=from]").val();
  var to = dealer.address +", "+ dealer.city +", "+ dealer.country;
  if (!from || !to) return false;
  var url = 'http://maps.google.com/maps?f=d&hl='+ config.mapLanguage +'&saddr='+ from +'&daddr='+ to;
  window.open(url);
  return false;
}


Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}

function sprintf( ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Ash Searle (http://hexmen.com/blog/)
    // + namespaced by: Michael White (http://crestidg.com)
    // *     example 1: sprintf("%01.2f", 123.1);
    // *     returns 1: 123.10
 
    var regex = /%%|%(\d+\$)?([-+#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
    var a = arguments, i = 0, format = a[i++];
 
    // pad()
    var pad = function(str, len, chr, leftJustify) {
        var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
        return leftJustify ? str + padding : padding + str;
    };
 
    // justify()
    var justify = function(value, prefix, leftJustify, minWidth, zeroPad) {
        var diff = minWidth - value.length;
        if (diff > 0) {
            if (leftJustify || !zeroPad) {
            value = pad(value, minWidth, ' ', leftJustify);
            } else {
            value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
            }
        }
        return value;
    };
 
    // formatBaseX()
    var formatBaseX = function(value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
        // Note: casts negative numbers to positive ones
        var number = value >>> 0;
        prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
        value = prefix + pad(number.toString(base), precision || 0, '0', false);
        return justify(value, prefix, leftJustify, minWidth, zeroPad);
    };
 
    // formatString()
    var formatString = function(value, leftJustify, minWidth, precision, zeroPad) {
        if (precision != null) {
            value = value.slice(0, precision);
        }
        return justify(value, '', leftJustify, minWidth, zeroPad);
    };
 
    // finalFormat()
    var doFormat = function(substring, valueIndex, flags, minWidth, _, precision, type) {
        if (substring == '%%') return '%';
 
        // parse flags
        var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false;
        for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) {
            case ' ': positivePrefix = ' '; break;
            case '+': positivePrefix = '+'; break;
            case '-': leftJustify = true; break;
            case '0': zeroPad = true; break;
            case '#': prefixBaseX = true; break;
        }
 
        // parameters may be null, undefined, empty-string or real valued
        // we want to ignore null, undefined and empty-string values
        if (!minWidth) {
            minWidth = 0;
        } else if (minWidth == '*') {
            minWidth = +a[i++];
        } else if (minWidth.charAt(0) == '*') {
            minWidth = +a[minWidth.slice(1, -1)];
        } else {
            minWidth = +minWidth;
        }
 
        // Note: undocumented perl feature:
        if (minWidth < 0) {
            minWidth = -minWidth;
            leftJustify = true;
        }
 
        if (!isFinite(minWidth)) {
            throw new Error('sprintf: (minimum-)width must be finite');
        }
 
        if (!precision) {
            precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);
        } else if (precision == '*') {
            precision = +a[i++];
        } else if (precision.charAt(0) == '*') {
            precision = +a[precision.slice(1, -1)];
        } else {
            precision = +precision;
        }
 
        // grab value using valueIndex if required?
        var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];
 
        switch (type) {
            case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad);
            case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
            case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
            case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
            case 'i':
            case 'd': {
                        var number = parseInt(+value);
                        var prefix = number < 0 ? '-' : positivePrefix;
                        value = prefix + pad(String(Math.abs(number)), precision, '0', false);
                        return justify(value, prefix, leftJustify, minWidth, zeroPad);
                    }
            case 'e':
            case 'E':
            case 'f':
            case 'F':
            case 'g':
            case 'G':
                        {
                        var number = +value;
                        var prefix = number < 0 ? '-' : positivePrefix;
                        var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
                        var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
                        value = prefix + Math.abs(number)[method](precision);
                        return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
                    }
            default: return substring;
        }
    };
 
    return format.replace(regex, doFormat);
}


$(window).unload( function () {
  GUnload();
});





/*
function setDealerCoordinates (pid, coordinates) {
  if (!pid || !coordinates) return false;
  var url = '/dealer_coordinates';
  var d = new Date();
  var updated = d.getFullYear() +"-"+ (d.getMonth() + 1) +"-"+ d.getDate();
  $.post(url, {
    "cmf_op": "edit",
    "cmf_pids": pid,
    "id": pid,
    "cmf_0_14": coordinates,
    "cmf_0_15": updated
  }, 
  function () {
  });
}
*/


/*
function getDealers (mode, param) {

  $("#zipsearch .zip").val("");
  zipLatLng = '';
  
  updateDealerlist();

  var params = new Object();
  if (selectedCountry)   params['country'] = selectedCountry;
  if (selectedState)     params['state'] = selectedState;
  if (selectedCity)      params['city'] = selectedCity; 
  // if (config.dealerType) params['type'] = config.dealerType;
  
  $.get("/dealer_locations.xml", params, function (data) {
  
    var countryOptions = '';
    var stateOptions = '';
    var cityOptions = '';
  
    // Countries
    if (!mode) {
      $("country", data).each( function () {
        var country = $(this).text();
        countryOptions += '<option value="'+ country +'">'+ country +'</option>';
      });
      
      // Select first option
      $(".country option:eq(0)").attr("selected", "selected");
    }
    
    // States
    if (mode == "country") {
      $(".state optgroup option").remove();
      $("state", data).each( function () {
        var state = $(this).text();
        stateOptions += '<option value="'+ state +'">'+ state +'</option>';
      });
      
      // Select first option
      $(".state option:eq(0)").attr("selected", "selected");
    }
    
    // Cities
    if (mode == "state") {
      $(".city optgroup option").remove();
      $("city", data).each( function () {
        var city = $(this).text();
        cityOptions += '<option value="'+ city +'">'+ city +'</option>';
      });
      
      // Select first option
      $(".city option:eq(0)").attr("selected", "selected");
    }
    
    // Append country/state/city options to selects, select first option
    if (countryOptions) {
      $(".country optgroup").append(countryOptions);
      $(".country option:eq(0)").attr("selected", "selected");
    }
    
    if (stateOptions) {
      $(".state optgroup").append(stateOptions);
      $(".state option:eq(0)").attr("selected", "selected");
    }
    
    if (cityOptions) {
      $(".city optgroup").append(cityOptions);
      $(".city option:eq(0)").attr("selected", "selected");
    }
  });
}
*/


  /*
    // Dealer coordinates not set, get with getLatLng()
    if (!dealer.coordinates) {
      
      var address = escape(dealer.address) +", "+ escape(dealer.city) +", "+ escape(dealer.country);
      var address2 = dealer.address +", "+ dealer.city +", "+ dealer.country;
      gm_gc.getLatLng(address, function (gLatLng) {
        if (gLatLng) {
          dealers[ pid ].marker = createDealerMarker(pid, gLatLng);
          dealerMarkers.push(dealers[ pid ].marker);
          // Store coordinates
          var coordinates = gLatLng.lat() +","+ gLatLng.lng();
          setDealerCoordinates(pid, coordinates);
        } 
        // Set coordinates to "x" (skips next getLatLng check)
        else {
          setDealerCoordinates(pid, "x");
        }
      });
    }
    // Use stored coordinatess
    else if (dealer.coordinates != 'x') {
      var latLng = dealer.coordinates.split(",");
      dealers[ pid ].marker = createDealerMarker(pid, new GLatLng(latLng[0], latLng[1]));
      dealerMarkers.push(dealers[ pid ].marker);
    }
  */    


  /*
  $.ajax({
    type:  "GET",
    async: false,
    cache: true,
    url:   "/dealers.xml",
    data:  '',
    dataType: 'xml',
    success: function (data) {
      $("a", data).each( function () {
        var pid = $(this).find("b").text();
        var dealer = new Object({
          "id":              $(this).find("c").text(),
          "name":            $(this).find("d").text(),
          "address":         $(this).find("e").text(),
          "address2":        $(this).find("f").text(),
          "zip":             $(this).find("g").text(),
          "city":            $(this).find("h").text(),
          "state":           $(this).find("i").text(),
          "country":         $(this).find("j").text(),
          "phone":           $(this).find("k").text(),
          "fax":             $(this).find("l").text(),
          "email":           $(this).find("m").text(),
          "website":         $(this).find("n").text(),
          "coordinates_lat": $(this).find("o").text(),
          "coordinates_lng": $(this).find("p").text()
          //"manager":     $(this).find("manager").text(),
          //"opentimes":   $(this).find("opentimes").text(),
        });
        dealers[ pid ] = dealer;
      });
    },
    complete: function () {
    }
  });
  */


/*
function selectCountry () {
  // Load cities
  // getDealers("country");
  getDealerLocations();
  
  // Focus on country
  gm_gc.getLatLng(selectedCountry, function (gLatLng) {
    gm_map.setCenter(gLatLng, countryZoomlevel);
  });
  
  // Enable state-select
  $(".state").removeAttr("disabled");
}
*/


/*
function selectState () {
  // Load states
  // getDealers("state");
  getDealerLocations();
  
  // Focus on state
  gm_gc.getLatLng(selectedState +", "+ selectedCountry, function (gLatLng) {
    gm_map.setCenter(gLatLng, stateZoomlevel);
  });
  
  // Enable city-select
  $(".city").removeAttr("disabled");
}
*/


/*
function selectCity () {
  // Focus on city
  gm_gc.getLatLng(selectedCity +", "+ selectedState, function (gLatLng) {
    gm_map.setCenter(gLatLng, cityZoomlevel);
    cityLatLng = gLatLng;
  });
}
*/

