
  // use Google API loader 
  google.load("maps", "2");
  google.load("search", "1");
  google.load("jquery", "1.2.6");

  var debug = false;  
  var map;
  var formData;
  var evtDragEnd;
  var evtZoomEnd;
  var savedCenter;
  
  var searcher;
  var searchControl;
  var cityZoom = 10;
  var poi; // point of interest
  var cp;
  var ttArray = new Array(); // array to store tooltips so could be removed while pan
  
  function initialize() 
  {      
    if (!GBrowserIsCompatible()) 
    {    
      alert("Your browser does not support Google Map.");
      return false;
    }

    // set up map
    map = new google.maps.Map2(document.getElementById("map_canvas"));
    var initZoomLevel = parseInt($("#initzoom").val());
    map.setCenter(new google.maps.LatLng($("#initlat").val(), $("#initlong").val()), initZoomLevel);
    map.addControl(new google.maps.LargeMapControl());
    //map.addControl(new google.maps.MapTypeControl());
    map.addMapType(G_PHYSICAL_MAP); // terrain
    //map.addControl(new ExtLargeMapControl());
    var initMapType = $('#initMapType').val();
    if (initMapType == "S")
      changeMapStyle('Satellite');
    else if (initMapType == "H")
      changeMapStyle('Hybrid');
    else if (initMapType == "T")
      changeMapStyle('Terrain');
    
    // local search control
    savedCenter = map.getCenter();
    searchControl = new google.search.SearchControl();
    searcher = new google.search.LocalSearch();
    var options = new google.search.SearcherOptions();
    options.setExpandMode(google.search.SearchControl.EXPAND_MODE_OPEN);
    searchControl.addSearcher(searcher , options);
    searchControl.setSearchCompleteCallback(searcher , OnLocalSearch);

    // drag zoom 
    var otherOpts = { 
      buttonHTML: "<img src='http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/tool_draw_sqaure.gif' title='Drag Zoom'>",
      buttonStyle: {border:0, width:'26px', height:'29px'},
      //buttonZoomingHTML: "<img src='http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/tool_hand_on.gif' title='Cancel Drag Zoom'>",
      buttonZoomingHTML: "<img src='http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/tool_draw_sqaure_on.gif' title='Cancel Drag Zoom'>",
      buttonZoomingStyle: {border:0, width:'26px', height:'29px'},

      // hand
      handButtonHTML: "<img src='http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/tool_hand_on.gif' title='Pan Mode'>",
      handButtonStyle: {border:0, width:'26px', height:'29px'},
      handButtonZoomingHTML: "<img src='http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/tool_hand.gif' title='Cancel Drag Zoom'>",
      handButtonZoomingStyle: {border:0, width:'26px', height:'29px'},
      
      stickyZoomEnabled: true,
      overlayRemoveTime: 1500,
      minDragSize: 10
    };
    var callbacks = {
      dragend: doSearch
    };
    var zcontrol = new DragZoomControl({}, otherOpts, callbacks);
    map.addControl(zcontrol, new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(80,10))); // drag zoom

    // pan
    evtDragEnd = google.maps.Event.addListener(map, "dragend", doMapEnd);
    
    // zoom in/out
    evtZoomEnd = google.maps.Event.addListener(map, "zoomend", doMapEnd);
    
    // when close info window, back to where it was
    google.maps.Event.addListener(map, "infowindowclose", function() {
      map.setCenter(savedCenter);
    });
    // message box
    map.addControl(new MessageOverlayControl());
    
    // community image hover
		setHover($(".community_button").find('img'));
    
    if ($("#initSearch").val() == "True")
    {
      doSearch();
    }
  }
  google.setOnLoadCallback(initialize);
  
  function doMapEnd() {
    $('#detachmap').attr('checked', 'true');
    doSearch();
  }

  // update search
  function submitSearch()
  {
    //alert("submitSearch");

    //map.clearOverlays();

    // save center point for infowindow closed to come back
    savedCenter = map.getCenter();
    if (debug) 
      google.maps.Log.write("[Map Center]" + savedCenter);
    
    // ajax loading icon
    ShowProgress();
    
    $("#minLat").val('');
    $("#maxLat").val('');
    $("#minLng").val('');
    $("#maxLng").val('');
    if ($('#detachmap').attr('checked'))
    {
      // get bounds
      var bounds = map.getBounds();
      if (debug)
        google.maps.Log.write("[Bounds]" + bounds);
      var southWest = bounds.getSouthWest();
      var northEast = bounds.getNorthEast();
      var minLat = southWest.lat();
      var maxLat = northEast.lat();
      var minLng = southWest.lng();
      var maxLng = northEast.lng();
      $("#minLat").val(minLat);
      $("#maxLat").val(maxLat);
      $("#minLng").val(minLng);
      $("#maxLng").val(maxLng);
    }
   
    // serialize form data
    //alert("form data Serialize");
    ////formData = $("form").serialize();
//    if (debug)
//      google.maps.Log.write("[Serialize]" + formData);

    var searchCriteria = s_arrayutil.serializeForm('searchForm');
    if ($("#serializedMoreFields").length)
			searchCriteria += "&" + $("#serializedMoreFields").val();
    if (debug)
      google.maps.Log.write("[Serialize]" + searchCriteria);
    mapSearch.searchListing(searchCriteria, "GetSearch");
  }
  
  // show profress
  function ShowProgress()
  {
    // show loader
    //$("#listingContainer").html("<img src='http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/ajax-loader.gif' />");
	  // show msgbox (same as VE)
	  $("#mapMsgBox").fadeIn("slow");
	  $("#mapMsgBox").html("Searching for listings...<br/>Please wait!");
		setTimeout("$('#mapMsgBox').fadeOut('slow')", 4000);
  }

  // create a marker
  var currMarkersArray = new Array();
  //
  function createMarker(point, mlsnum, info, myIcon, i)
  {
    //var marker = new google.maps.Marker(point, { icon:myIcon });
    
    var mkropts = { 
      "icon": myIcon,
      "clickable": true,
      "labelText": "<font size='0.1px' color='#ffffff'>" + (i + 1) + "</font>",
      "labelOffset": new GSize(-3, -30)
    };
    var marker = new LabeledMarker(point, mkropts);
    currMarkersArray.push(marker);
    
    var tooltip = document.createElement("div");
    //var dt = new Date();
    tooltip.setAttribute('id', 'tt_'+ mlsnum);
    document.getElementById("map_canvas").appendChild(tooltip);
    ttArray.push(tooltip);
    tooltip.style.visibility = "hidden";
    marker.tooltip = info;

    var point = map.getCurrentMapType().getProjection().fromLatLngToPixel(map.getBounds().getSouthWest(), map.getZoom());
    var offset = map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(), map.getZoom());
    var anchor = marker.getIcon().iconAnchor;
    var width = marker.getIcon().iconSize.width;
    //var pos = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(180,75)); 
    var cx = offset.x - point.x - anchor.x + width;
    if (offset.x > cp.x) {
      cx = cx - 310;
    }
    var pos = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, 
      new GSize(cx, - offset.y + point.y + anchor.y - 100)); 

    tooltip.innerHTML = info;
    pos.apply(tooltip);

    // mouse-over to show tooltip
    google.maps.Event.addListener(marker, "mouseover", function() {
      tooltip.style.visibility = "visible";
    });
    // mouse-out to hide tooltip
    google.maps.Event.addListener(marker, "mouseout", function() {
      tooltip.style.visibility = 'hidden';
    });
    // click to view detail
    google.maps.Event.addListener(marker, "click", function() {
      s_mapResult.getDetail(mlsnum);
    });
    
    map.addOverlay(marker);
  }

  var currentMarker;
  function closeOverlay() 
  {
    if (currentMarker) {
      map.setCenter(savedCenter);
      map.removeOverlay(currentMarker.overlay);
      currentMarker.show();
    }
  }

  // create markers
  function createMarkers(listings) 
  {
    cp = map.getCurrentMapType().getProjection().fromLatLngToPixel(map.getCenter(), map.getZoom());

    // clean tooltips
    CleanToolTips();
  
    for (var i = 0; i < listings.length; i++)
    {
      var listing = listings[i];
      var point = new google.maps.LatLng(listing.latitude, listing.longitude);
      var mlsnum = listing.mlsNum;
      //var info = listing.infoBox;
      var info = s_mapResult.printInfoBoxNoLinks(mlsnum, "");
      // icon
      var myIcon = new google.maps.Icon(G_DEFAULT_ICON);
      myIcon.image = listing.icon;
      myIcon.mozPrintImage = "";
      myIcon.printImage = "";
      myIcon.iconSize = new google.maps.Size(23, 21);
      myIcon.shadow = "";
      // add marker
      createMarker(point, mlsnum, info, myIcon, i);
    }
  }
  
  // remove tooltip Div(s) before place new ones
  function CleanToolTips()
  {
    var mapDiv = document.getElementById("map_canvas");
    for (var m = 0; m < ttArray.length; m++) {
      mapDiv.removeChild(ttArray[m]);
    }
    ttArray = new Array();

    /*
    var ttDivs = mapDiv.childNodes;
    for (var i = 0; i < ttDivs.length; i++) {
      //alert(ttDivs[i].id);
      if (ttDivs[i].id.indexOf('tt_') == 0) {
        // remove previous tootips
        //alert('remove: ' + ttDivs[i].id);
        mapDiv.removeChild(ttDivs[i]);
      }
    }
    */
  }
  
  function GetSearch(args) 
  {
    //map.clearOverlays();
    if (currMarkersArray != null)
    {
      for (var j = 0; j < currMarkersArray.length; j++)
        map.removeOverlay(currMarkersArray[j]);
    }
    
	  // add markers & container
		s_mapResult.init(args.result);
		var totalCount = s_mapResult.mapResult.count;
		$("#listingCount").html(totalCount);
	  var mylistings = args.result.listings;
    if (totalCount > 0 && totalCount < 200)
    {
	    createMarkers(mylistings);
		  s_mapResult.printPage(0);
		  if (!$('#detachmap').attr('checked')) {
		    if (s_mapResult.centerLat != '') {
		      map.setCenter(new google.maps.LatLng(s_mapResult.centerLat, s_mapResult.centerLng), 10);
		    }
		  }
		}
		else if (totalCount > 0)
		{ // more than 200
		  $("#mapMsgBox").fadeIn("slow");
		  $("#mapMsgBox").html("Too many listings (>200). Narrow your search criteria or <a href=\"javascript:changeZoom()\">zoom in</a>.");
  		setTimeout("$('#mapMsgBox').fadeOut('slow')", 4000);
		  s_mapResult.printPage(0);
		  if (!$('#detachmap').attr('checked')) {
		    if (s_mapResult.centerLat != '') {
		      map.setCenter(new google.maps.LatLng(s_mapResult.centerLat, s_mapResult.centerLng), 11);
		    }
		  }
		}
		else
		{ // no results
      $("#listingContainer").html("No results found.");
		}
  }
  
  // change select mode
  function changeSelectMode()
  {
    var radius = $('#circleRadius').val();
    if (radius != "")
    { // radius search
      $('#selectmode').val('circle');
    }        
  }
  
  function changeTab(id)
  {
    if (id == "tab1")
    {
			$("#tab2").hide();
			$("#radiusTab").attr("class", "tab2");
			$("#tab1").show();
			$("#locationTab").attr("class", "tab1");
      $("#acSearch").focus();
      removeRadius(); // clean radius criteria
    }
    else
    { // tab2
			$("#tab1").hide();
			$("#locationTab").attr("class", "tab2");
			$("#tab2").show();
			$("#radiusTab").attr("class", "tab1");
      $("#findfield").focus();
      removeAllCities(); // clean location
    }
  }
  
  /**
   * Add a circle to the global variable "map". This function won't work for circles that encompass
   * the North or South Pole. Also, there is a slight distortion in the upper-left, upper-right,
   * lower-left, and lower-right sections of the circle that worsens as it gets larger and/or closer
   * to a pole.
   * @param lat Latitude in degrees
   * @param lng Longitude in degrees
   * @param radius Radius of the circle in statute miles
   * @param {String} strokeColor Color of the circle outline in HTML hex style, e.g. "#FF0000"
   * @param strokeWidth Width of the circle outline in pixels
   * @param strokeOpacity Opacity of the circle outline between 0.0 and 1.0
   * @param {String} fillColor Color of the inside of the circle in HTML hex style, e.g. "#FF0000"
   * @param fillOpacity Opacity of the inside of the circle between 0.0 and 1.0
   */
  function drawCircle(lat, lng, radius, strokeColor, strokeWidth, strokeOpacity, fillColor, fillOpacity) 
  {
    var d2r = Math.PI / 180;
    var r2d = 180 / Math.PI; 
    var Clat = (radius / 3963) * r2d; 
    var Clng = Clat / Math.cos(lat * d2r); 
    var Cpoints = []; 
    for (var i = 0; i < 33; i++) 
    {
      var theta = Math.PI * (i / 16);
      Cy = lat + (Clat * Math.sin(theta));
      Cx = lng + (Clng * Math.cos(theta));
      var P = new GPoint(Cx, Cy);
      Cpoints.push(P);
    }
    var polygon = new GPolygon(Cpoints, strokeColor, strokeWidth, strokeOpacity, fillColor, fillOpacity);
    map.addOverlay(polygon);
  }

  // poi + radius search
  function doSearch()
  {
    //map.clearOverlays();
    var poi = $('#findfield').val();
    
    if (poi != "")
    {
      var geocoder = new GClientGeocoder();
      if (geocoder)
      {
        geocoder.getLatLng(poi, function(point) {
            if (!point) 
            {
              alert(poi + " not found");
            } 
            else 
            {
              //alert("put POI marker");
              //map.setCenter(point, 13);
              map.setCenter(point);
              var marker = new GMarker(point);
              map.addOverlay(marker);
              // draw circle
              drawCircle(point.y, point.x, $('#circleRadius').val(), "#CCFFCC", 1, 0.75, "#CCFFCC", 0.5)
              // set latLng hidden cuz poi search
              $('#latlong').val(point.y + "," + point.x);
              submitSearch();
            }
          }
        );
      }
    }
    else
    { // no poi search
      // change the selectmode to VIEW
      $('#selectmode').val('view');
      submitSearch();
    }
  }
  
  // local search
  var poiIcon = null;
  function LocalSearch(str)
  {
    // poi icon
    poiIcon = new google.maps.Icon();
    poiIcon.image = "http://elements6.superlativestudio.com/AppInterface/Default/MapSearch/images/icon-"+ str +"_sm.gif"
    poiIcon.iconSize = new google.maps.Size(19, 19);
    poiIcon.iconAnchor = new google.maps.Point(6, 20);
    poiIcon.infoWindowAnchor = new google.maps.Point(5, 1);

    // show markers
    searcher.setCenterPoint(map);
    searchControl.draw(null);
    searchControl.execute(str);
    
    // dim icon
		$(".community_button").find("img").attr("src", function () {
			var src1 = $(this).attr("src");
			if ($(this).parent().attr("href") == "javascript:LocalSearch('" + str + "')") 
			{
				if (src1.indexOf("_2.gif") != -1) 
					src1 = src1.replace("_2.gif",".gif");
				else 
				  src1 = src1.replace(".gif","_2.gif");
			}
			else 
			{
				if (src1.indexOf("_2.gif") != -1) 
				  src1 = src1.replace("_2.gif",".gif");
			}
      return src1;
    });
  }

  function OnLocalSearch()
  {
    var results = searcher.results;
    
    //alert(results.length);
    for (var i = 0; i < results.length; i++) 
    {
      var result = results[i];
      var markerLatLng = new google.maps.LatLng(parseFloat(result.lat), parseFloat(result.lng));
      var marker = new google.maps.Marker(markerLatLng, {icon : poiIcon});
      marker.bindInfoWindow(result.html.cloneNode(true));
      map.addOverlay(marker);
      if (i == 0)
      { // move map center to 1st marker
        //map.setCenter(markerLatLng, cityZoom);
        //map.setCenter(markerLatLng);
        //savedCenter = markerLatLng;
        if (poi != "")
        {
          //$('#latlong').val(result.lat + "," + result.lng);
          if (debug)
            google.maps.Log.write("[POI Center]" + savedCenter);
          //alert($('#latlong').val());
        }
      }
    }
  }

  function changeZoom()
  {
    map.zoomIn();
  }
  
  // change map type
	function changeMapStyle(style) {
		switch(style) {
			case "Map":
				map.setMapType(G_NORMAL_MAP);
				break;
			case "Satellite":
				map.setMapType(G_SATELLITE_MAP);
				break;
			case "Hybrid":
				map.setMapType(G_HYBRID_MAP);
				break;
			case "Terrain":
				map.setMapType(G_PHYSICAL_MAP);
				break;
		}
		$(".button_on,.button_off").each(function(){
			if (this.firstChild.innerText == style)
				this.className = "button_off";
			else
				this.className = "button_on";
		});
	}
  
  // community icons hover
  function setHover(elmt) {
		elmt.hover(
			function () {
				var src = $(this).attr("src");
				if (src.indexOf("_2.gif") != -1) src = src.replace("_2.gif",".gif");
				else src = src.replace(".gif","_2.gif");
				$(this).attr("src",src);
			}, 
			function () {
				var src = $(this).attr("src");
				if (src.indexOf("_2.gif") != -1) src = src.replace("_2.gif",".gif");
				else src = src.replace(".gif","_2.gif");
				$(this).attr("src",src);
			}
		);
  }
  
  
