
function JStoreLocationsMap()
{
  //private member variables
  var m_map;
  var m_geocoder;
  var m_StoreLocator;
  var m_lastError;
  var m_icon;
  var m_markers;
  var m_bBrowserCompatible;
  var m_bBaseLocationValid;
  var m_bLocationsCalculated;
  var m_detailZoom;
  var m_strBubbleHTML;
  var m_strLocationInfoHTML;
  var m_locationInformationElementId;
  var m_xmlHttp;
  var m_requests;
  var m_iLocationsToShow;
  var m_clickZoomThreshold;
  var m_mapClickHandle;
  var m_locationInformationRows;
  var m_resultHeaderText;
  
  //public methods
  this.BrowserCompatible = BrowserCompatible;
  this.LocationsCalculated = LocationsCalculated;
  this.BaseLocationValid = BaseLocationValid;
  this.GetMap = GetMap;
  this.DisplayMap = DisplayMap;
  this.GetStoreLocator = GetStoreLocator;
  this.Initialize = Initialize;
  this.LastError = GetLastError;
  this.SetMapCenter = SetMapCenter;
  this.GetMapZoom = GetMapZoom;
  this.GetIcon = GetIcon;
  this.CenterLocation = CenterLocation;
  this.ShowAddress = ShowAddress;
  this.SetBubbleInfo = SetBubbleInfo;
  this.addStoreLocation = addStoreLocation;
  this.GetMarkerArray = GetMarkerArray;
  this.SetMarkerArray = SetMarkerArray;
  this.NewMarkerArray = NewMarkerArray;
  this.getStoreLocationBubbleInfo = getStoreLocationBubbleInfo;
  this.SetLocationInformationElementId = SetLocationInformationElementId;
  this.GetLocationInformationElementId = GetLocationInformationElementId;
  this.GetXmlHttpObject = GetXmlHttpObject;
  this.AddRequest = AddRequest;
  this.GetNumberOfStoresToDisplay = GetNumberOfStoresToDisplay;
  this.m_iLocationsToShow = m_iLocationsToShow;
  this.DefaultMapCenter = DefaultMapCenter;
  this.m_clickZoomThreshold = m_clickZoomThreshold;
  this.m_mapClickHandle = m_mapClickHandle;
  this.GetResultHeader = GetResultHeader;
  this.GetLocationInformationTable = GetLocationInformationTable;
  this.m_locationInformationRows = m_locationInformationRows;
  this.m_resultHeaderText = m_resultHeaderText;
  
  m_bBaseLocationValid = false;
  m_bBrowserCompatible = false;
  m_bLocationsCalculated = false;
  m_detailZoom = 13;
  m_iLocationsToShow = 5;
  this.m_clickZoomThreshold = 6;
  
  function Initialize()
  {
    m_geocoder = new GClientGeocoder();
    
    if ( !GBrowserIsCompatible() )
    {
      m_bBrowserCompatible = false;
      return false;
    }
    else
      m_bBrowserCompatible = true;
      
    GetWindowSize();
    var height = windowsize.height;
    var width = windowsize.width;    
    
    m_StoreLocator = new JStoreLocator();
    m_bLocationsCalculated = GetStoreLocator().LocationsCalculated();
    if ( !GetStoreLocator().BaseLocation().Valid() )
    {
      m_bBaseLocationValid = false;
    }
    else
      m_bBaseLocationValid = true;
      
    this.m_iLocationsToShow = 5;
    document.getElementById("showlocationsrow").style.display = "none";
    
    this.m_resultHeaderText = this.GetResultHeader().firstChild.nodeValue;
    
    return true;
  }
  
  function GetResultHeader()
  {
    return document.getElementById("closestlocations");
  }
  
  function GetLocationInformationTable()
  {
    var table = document.getElementById("locationInfoTable").lastChild;
    return table;
  }
  
  function BrowserCompatible()
  {
    return m_bBrowserCompatible;
  }
  
  function LocationsCalculated()
  {
    return m_bLocationsCalculated;
  }
  
  function BaseLocationValid()
  {
    return m_bBaseLocationValid;
  }
  
  function GetMap()
  {
    return m_map;
  }
  
  function GetStoreLocator()
  {
    return m_StoreLocator;
  }
  
  function DisplayMap( strElementId, clickHandler, handlerContext )
  {
    m_map = new GMap2( document.getElementById( strElementId ) );
    m_map.addControl(new GLargeMapControl());
    m_map.addControl(new GMapTypeControl());
    var center = GetStoreLocator().BaseLocation().Point();
    if ( this.BaseLocationValid() )
      SetMapCenter( center );
    else
      DefaultMapCenter();
    
    /*if ( !this.GetStoreLocator().LocationsCalculated() )
    {
      var _this = this;
      this.m_mapClickHandle = GEvent.addListener(this.GetMap(), "click", function(marker, point) {
			  _this.MapClick.call( _this, point, clickHandler, handlerContext );
		  });
		}*/
  }
  
  function SetMapCenter( point )
  {
    GetMap().setCenter(new GLatLng(point.Latitude(), point.Longitude()), GetMapZoom() );
    var marker = new GMarker(GetMap().getCenter());
    if ( point.Valid() )
      GetMap().addOverlay( marker );
  }
  
  function DefaultMapCenter()
  {
    //Memphis, Tennessee
    var memphis = new GLatLng( 35.149444, -90.048889 );
    //Wichita, Kansas
    var wichita = new GLatLng( 37.692222, -97.337222 );
    GetMap().setCenter( wichita, 3 );
  }

  function GetMapZoom()
  {
    var swpoint, nepoint, bounds, zoom;
    swpoint = new GLatLng( GetStoreLocator().GetSWZoomBound().Latitude(), GetStoreLocator().GetSWZoomBound().Longitude() );
    nepoint = new GLatLng( GetStoreLocator().GetNEZoomBound().Latitude(), GetStoreLocator().GetNEZoomBound().Longitude() );
    
    bounds = new GLatLngBounds( swpoint, nepoint );
    zoom = GetMap().getBoundsZoomLevel( bounds );
    if ( zoom < 1  ||  zoom > 18 )
      zoom = m_detailZoom;
      
    return zoom;
  }
  
  function GetNumberOfStoresToDisplay()
  {
    var numStores = this.GetStoreLocator().NumberOfStores();
    var displayStores = numStores;
    if (( this.m_iLocationsToShow < numStores ) && ( this.m_iLocationsToShow >= 0 ))
      displayStores = this.m_iLocationsToShow;
    return displayStores;
  }
  
  function addStoreLocation( istoreLocation, marker )
  {
    GetMap().addOverlay( marker );
    m_markers[ istoreLocation ] = marker;
  }
  
  function getStoreLocationBubbleInfo( store )
  {
    var strHTML = "";
    strHTML += "<div style=\"width:250px;\">";
    strHTML += "<div style=\"float:right;\">";
    strHTML += "<img src=\"aamcologo3.png\"><br />\n";
    strHTML += "</div>";
    strHTML += "Aamco of ";
    strHTML += store.City() + ", ";
    strHTML += store.State() + "<br />\n";
    strHTML += store.StreetAddress() + "<br />\n";
    strHTML += "Phone: " + store.PhoneNumber() + "<br /><br />\n";
    if ( store.HasWebAddress() )
      strHTML += "<b><a href=\"" + store.Website() + "\">Visit Our "+store.GetWebAddressType()+"</a><img src=\"locato1.gif\"></b><br />\n";
    if ( store.ScheduleOnlineAppointments() )
      strHTML += "<img src=\"swoosh_sml.gif\"> Schedule online appointment<br />";
    if ( store.SpecialOnlineOffers() )
      strHTML += "<img src=\"swoosh_sml.gif\"> Special online offers<br />";
    if ( store.TransmissionService() )
      strHTML += "<img src=\"swoosh_sml.gif\"> Transmission service<br />";
    if ( store.CompleteCarCare() )
      strHTML += "<img src=\"swoosh_sml.gif\"> Complete car care service<br />";
    if ( store.HasWebAddress() )
      strHTML += "<b><a href=\"" + store.Website() + "\">Visit Our "+store.GetWebAddressType()+"</a><img src=\"locato1.gif\"></b><br />\n";
    strHTML += "</div";
    return strHTML;
  }
  
  function GetLastError()
  {
    return m_lastError;
  }
  
  function SetError( strErrMsg )
  {
    m_lastError = strErrMsg;
  }
  
  function GetIcon()
  {
    var icon = new GIcon();
    icon.image = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
    //icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    icon.iconSize = new GSize(35, 30);
    //icon.shadowSize = new GSize(22, 20);
    icon.iconAnchor = new GPoint(20, 30);
    icon.infoWindowAnchor = new GPoint(30, 5);
    return icon;
  }
  
  function CenterLocation( i )
  {
    var store = GetStoreLocator().StoreLocations()[i];
    var currentZoomLevel = GetMap().getZoom();
    var zoomLevel = m_detailZoom;
    if ( currentZoomLevel > zoomLevel )
      zoomLevel = currentZoomLevel;
    
    m_markers[i].openInfoWindowHtml( getStoreLocationBubbleInfo( store ));
    GetMap().setCenter(new GLatLng(store.BaseLocation().Point().Latitude(), store.BaseLocation().Point().Longitude()) );
    GetMap().setZoom( zoomLevel );
  }
  
  function ShowAddress( address, notFoundId )
  {
    if ( this.m_mapClickHandle)
      GEvent.removeListener( this.m_mapClickHandle );
      
    this.Reset();
    var _this = this;
    this.GetGeocoder().getLatLng( address,
      function (point)
      {
        if ( !point )
        {
          document.getElementById( notFoundId ).innerHTML = " " + address + " could not be found.";
        }
        else
        {
          GetMap().setCenter(point, m_detailZoom);
          var marker = new GMarker(point, {draggable:true});
          GetMap().addOverlay(marker);
          GEvent.addListener(marker, "dragstart", function() {
            _this.GetMap().closeInfoWindow();
          });
          GEvent.addListener(marker, "dragend", function() {
            marker.openInfoWindowHtml(marker.getPoint().lat()+", "+marker.getPoint().lng());
          });
          marker.openInfoWindowHtml( point.lat() + ", " + point.lng() );          
          document.getElementById( notFoundId ).innerHTML = "";
        }
      }
    );
  }
  
  
  
  function SetBubbleInfo()
  {
  
  }
  
  function GetMarkerArray()
  {
    return m_markers;
  }
  
  function SetMarkerArray( array )
  {
    m_markers = array;
  }
  
  function NewMarkerArray()
  {
    m_markers = new Array();
  }
  
  function SetLocationInformationElementId( strId )
  {
    m_locationInformationElementId = strId;
  }
  
  function GetLocationInformationElementId()
  {
    return m_locationInformationElementId;
  }
  
  function GetXmlHttpObject()
  {
    m_xmlHttp = false;
    if (window.XMLHttpRequest) // Mozilla, Safari,...
    { 
      m_xmlHttp = new XMLHttpRequest();
      //if ( m_xmlHttp.overrideMimeType )
      //  m_xmlHttp.overrideMimeType( "text/xml" );
    } 
    else if (window.ActiveXObject) // IE
    {
      try
      {
        m_xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
      } 
      catch (e)
      {
        try
        {
           m_xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } 
        catch (e) {}
      }
    }
    return m_xmlHttp;
  }
  
  function AddRequest( xmlHttp )
  {
    if ( !m_requests )
      m_requests = new Array();
      
    m_requests.push(xmlHttp);
  }

}

function GetWindowSize()
{
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  windowsize.height = myHeight;
  windowsize.width = myWidth;
  return windowsize;
}

var windowsize = { height: 0, width: 0 };


JStoreLocationsMap.prototype.MapClick = function( point, clickHandler, handlerContext )
{
  var zoomlevel = this.GetMap().getZoom();
  if (zoomlevel < this.m_clickZoomThreshold)
  {
    this.GetMap().setCenter( point );
    this.GetMap().setZoom( this.m_clickZoomThreshold );
    return;
  }
  if (!point)
    return;
	var strPoint = point.toUrlValue();
	var splitPoint = strPoint.split(",");
	var p = { latitude:splitPoint[0], longitude: splitPoint[1] };
	clickHandler.call( handlerContext, p );
}

JStoreLocationsMap.prototype.DisplayStoreMarkers = function()
{
  var x;
  var stores = this.GetStoreLocator().StoreLocations();
  var marker, markerPoint;
  var storeLocation;
  
  this.GetMap().clearOverlays();
  this.NewMarkerArray();

  for (x = 0; x < this.GetNumberOfStoresToDisplay(); x++)
  {
    storeLocation = stores[x];
    markerPoint = storeLocation.BaseLocation().Point();
    marker = this.newStoreLocationMarker( markerPoint, storeLocation, x );
    this.addStoreLocation( x, marker );
  }
}

JStoreLocationsMap.prototype.newStoreLocationMarker = function( markerPoint, store, istoreLocation )
{
  var point = new GLatLng( markerPoint.Latitude(), markerPoint.Longitude() );
  var marker = new GMarker( point, {draggable:false, icon: this.GetIcon()});
  var centerLocFunc = this.CenterLocation;
  
  GEvent.addListener(marker, "click", function() {
    centerLocFunc( istoreLocation );
  });
      
  return marker;
}

JStoreLocationsMap.prototype.ActivateLink = function( strId, func, arg )
{
  var span = document.getElementById( strId );
  var text = span.firstChild;
  if ((text.id) && (text.id == (strId + "link")))
    return;
  var link = document.createElement("a");
  var linktext = document.createTextNode(text.nodeValue);
  link.appendChild( linktext );
  
  link.href = "#";
  link.id = strId + "link";
  var _this = this;
  link.onclick = function()
    { func.call( _this, arg ); return false; };
  span.replaceChild( link, text );
}

JStoreLocationsMap.prototype.DeactivateLink = function( strId )
{
  var span = document.getElementById( strId );
  var link = document.getElementById( strId + "link" );
  if (!link)
    return;
  var text = link.firstChild.nodeValue;
  var textnode = document.createTextNode( text );
  span.replaceChild( textnode, link );
}

JStoreLocationsMap.prototype.ToggleLocationsToShow = function()
{
  var numStores = this.GetStoreLocator().NumberOfStores();
  var radius = this.GetStoreLocator().GetSearchRadius();
  var city = this.GetStoreLocator().BaseLocation().City();
  var state = this.GetStoreLocator().BaseLocation().State();
  if (this.GetStoreLocator().LocationsCalculated())
    document.getElementById("headermessage").innerHTML = "<br />There are " + numStores + " locations within a " + radius + " mile radius of " + city + ", " + state + ".";
  else
    document.getElementById("headermessage").innerHTML = "";
  
  if ( numStores == 0 )
    document.getElementById("showlocationsrow").style.display = "none";
  else
    document.getElementById("showlocationsrow").style.display = "";
  
  if (( this.m_iLocationsToShow != 5 ) && ( numStores > 0 ))
    this.ActivateLink( "showlocations1", this.ShowNumberOfLocations, 5 );
  else
    this.DeactivateLink( "showlocations1" );
  if (( this.m_iLocationsToShow != 10 ) && ( numStores >= 6 ))
    this.ActivateLink( "showlocations2", this.ShowNumberOfLocations, 10 );
  else
    this.DeactivateLink( "showlocations2" );
  if (( this.m_iLocationsToShow != 15 ) && ( numStores >= 11 ))
    this.ActivateLink( "showlocations3", this.ShowNumberOfLocations, 15 );
  else
    this.DeactivateLink( "showlocations3" );
  if (( this.m_iLocationsToShow != -1 ) && ( numStores > this.m_iLocationsToShow ))
    this.ActivateLink( "showlocations4", this.ShowNumberOfLocations, -1 );
  else
    this.DeactivateLink( "showlocations4" );
}

JStoreLocationsMap.prototype.DisplayResultHeader = function()
{
  var resultHeaderSpan = this.GetResultHeader();
  var resultHeaderTextNode = resultHeaderSpan.firstChild;
  var resultHeaderText = this.m_resultHeaderText;
  resultHeaderText = resultHeaderText.replace( /#/, this.GetNumberOfStoresToDisplay() );
  resultHeaderText = resultHeaderText.replace( /\$/, this.GetStoreLocator().GetSearchRadius() );
  var newResultHeaderTextNode = document.createTextNode( resultHeaderText );
  resultHeaderSpan.replaceChild( newResultHeaderTextNode, resultHeaderTextNode );
}

JStoreLocationsMap.prototype.DisplayLocationInformation = function( strElementId )
{
  if ( !strElementId )
    return;
  var i;
  var strHTML;
  
  this.SetLocationInformationElementId( strElementId );
  this.ToggleLocationsToShow();
  if ( this.GetStoreLocator().LocationsCalculated() )
  {
    document.getElementById( strElementId ).style.display = "";
    this.GetResultHeader().style.display = "";
  }
  else
  {
    document.getElementById( strElementId ).style.display = "none";
    this.GetResultHeader().style.display = "none";
  }
  
  this.DisplayResultHeader();
  
  var table = this.GetLocationInformationTable();
  var tr;
  //delete previous table rows
  if ( !this.m_locationInformationRows )
    this.m_locationInformationRows = new Array();

  var rowlength = this.m_locationInformationRows.length;
  for (i = 0; i < rowlength; i++)
  {
    tr = this.m_locationInformationRows.pop();
    table.removeChild( tr );
  }
  
  //add new table rows
  for (i = 0; i < this.GetNumberOfStoresToDisplay(); i++)
  {
    tr = document.createElement("tr");
    tr = this.AppendLocationInformationRow( i, tr );
    table.appendChild( tr );
    this.m_locationInformationRows.push( tr );
  }
  this.PopulateLocationInformation();
  setActiveStyleSheet("storelocator");
}

JStoreLocationsMap.prototype.AppendLocationInformationRow = function( i, tr )
{
  var store = this.GetStoreLocator().StoreLocations()[i];
  
  var milestd = document.createElement("td");
  milestd.setAttribute("align","center");
  milestd.setAttribute("class","locinfotd");
  milestd.setAttribute("id","milestd"+i);
  milestd.style.border = "solid 1px #BBBBBB";
  milestd.style.padding = "5px 5px 5px 5px";
  var milestext = document.createTextNode( store.Miles() );
  milestd.appendChild( milestext );
  var infotd = document.createElement("td");
  infotd.setAttribute("align","left");
  infotd.setAttribute("class","locinfotd");
  infotd.setAttribute("id","infotd"+i);
  infotd.style.border = "solid 1px #BBBBBB";
  infotd.style.padding = "5px 5px 5px 5px";
  var apptstd = document.createElement("td");
  apptstd.setAttribute("align","center");
  apptstd.setAttribute("class","locinfotd");
  apptstd.setAttribute("id","apptstd"+i);
  apptstd.style.border = "solid 1px #BBBBBB";
  apptstd.style.padding = "5px 5px 5px 5px";
  var offerstd = document.createElement("td");
  offerstd.setAttribute("align","center");
  offerstd.setAttribute("class","locinfotd");
  offerstd.setAttribute("id","offerstd"+i);
  offerstd.style.border = "solid 1px #BBBBBB";
  offerstd.style.padding = "5px 5px 5px 5px";
  var transtd = document.createElement("td");
  transtd.setAttribute("align","center");
  transtd.setAttribute("class","locinfotd");
  transtd.setAttribute("id","transtd"+i);
  transtd.style.border = "solid 1px #BBBBBB";
  transtd.style.padding = "5px 5px 5px 5px";
  var completetd = document.createElement("td");
  completetd.setAttribute("align","center");
  completetd.setAttribute("class","locinfotd");
  completetd.setAttribute("id","completetd"+i);
  completetd.style.border = "solid 1px #BBBBBB";
  completetd.style.padding = "5px 5px 5px 5px";
  tr.appendChild(milestd);
  tr.appendChild(infotd);
  tr.appendChild(apptstd);
  tr.appendChild(offerstd);
  tr.appendChild(transtd);
  tr.appendChild(completetd);
  return tr;
}

JStoreLocationsMap.prototype.PopulateLocationInformation = function()
{
  var i;
  for (i = 0; i < this.GetNumberOfStoresToDisplay(); i++)
  {
    this.PopulateLocationInformationRow( i );
  }
}

JStoreLocationsMap.prototype.PopulateLocationInformationRow = function( i )
{
  var store = this.GetStoreLocator().StoreLocations()[i];
  var strHTML = "";
  strHTML += store.City() + ", ";
  strHTML += store.State() + " (<a href=\"#\" onclick=\"Javascript:centerStoreLocation("+i+");return false;\">Zoom map</a>)<br />\n";
  if ( store.HasWebAddress() )
    strHTML += "<a href=\"" + store.Website() + "\">Visit "+store.GetWebAddressType()+"</a><img src=\"locato1.gif\"><br />\n";
  strHTML += store.StreetAddress() + "<br />\n";
  strHTML += "Phone: " + store.PhoneNumber() + "\n";
  strHTML += this.GetAdditionalLocationInformation( i );
  
  document.getElementById("infotd"+i).innerHTML = strHTML;
  document.getElementById("apptstd"+i).innerHTML = this.GetLocationInformationCheckboxHTML( store.ScheduleOnlineAppointments(), i );
  document.getElementById("offerstd"+i).innerHTML = this.GetLocationInformationCheckboxHTML( store.SpecialOnlineOffers(), i );
  document.getElementById("transtd"+i).innerHTML = this.GetLocationInformationCheckboxHTML( store.TransmissionService(), i );
  document.getElementById("completetd"+i).innerHTML = this.GetLocationInformationCheckboxHTML( store.CompleteCarCare(), i );
}

JStoreLocationsMap.prototype.GetAdditionalLocationInformation = function( i )
{
  return "";
}

JStoreLocationsMap.prototype.GetLocationInformationCheckboxHTML = function( val, i )
{
  var strHTML = "";
  if ( val )
    strHTML += "<img src=\"locato2.gif\" />";
  else
    strHTML += " - ";
    
  return strHTML;
}

JStoreLocationsMap.prototype.Reset = function()
{
  this.GetStoreLocator().Reset();
  this.GetMap().clearOverlays();
  this.NewMarkerArray();
  this.GetStoreLocator().SetLocationsCalculated( false );
  this.DisplayLocationInformation( this.GetLocationInformationElementId() );
  this.DefaultMapCenter();
}

JStoreLocationsMap.prototype.SendRequest = function( script, requestString, cache, callback, callingContext )
{
  var xmlHttp = this.GetXmlHttpObject();
  if ( !xmlHttp )
    return false;
    
  var url = script + "?" + requestString
  if ( !cache )
    url += "&sid=" + Math.random();
  
  var _this = this;
  
  xmlHttp.open( "GET", url, true );
  xmlHttp.onreadystatechange = function() {
    if (( xmlHttp.readyState == 4 ) || ( xmlHttp.readyState == "complete" ))
      _this.HandleResponse( xmlHttp.responseText, callback, _this, callingContext );
  };
  xmlHttp.send( null );
  this.AddRequest( xmlHttp );
  return xmlHttp;
}

JStoreLocationsMap.prototype.HandleResponse = function( strResponse, callback, context, callingContext )
{
  if ( !callback )
    return;

  callback.call( context, strResponse, callingContext );
}

JStoreLocationsMap.prototype.GetGeocoder = function()
{
  if ( !this.m_geocoder )
    this.m_geocoder = new GClientGeocoder;
    
  return this.m_geocoder;
}

JStoreLocationsMap.prototype.ShowNumberOfLocations = function( n )
{  
  this.m_iLocationsToShow = n;
  var center = this.GetStoreLocator().BaseLocation().Point();
  this.SetMapCenter( center );
  this.DisplayStoreMarkers();
  this.DisplayLocationInformation( this.GetLocationInformationElementId() );
}