/**
 * Dependencies : 
 * 	- MMViewer api
 */

function MMProperties() 
{
	mapviewer:null;
	dealerLocation:null;
	userLocation:null;	
	locations:null;
	timeoutId:null;
	timeoutOccurred:false;
	this.timeoutInterval = 30000;	//in milliseconds
	
	/* Route */
	route:null;
	route_finder:null;
	this.markers=new Array();
	
	/* Status flags */
	isReverse:false;
	loading:false;
	
	/* Constants */
	DEFAULT_MAP_ZOOM_FACTOR:15;
	MAX_Z_INDEX:1000;
	MAX_ZOOM_FACTOR:20;
}

var mmProperties, fdDealerLocation; 
var countries = new Array();
countries['US'] = 'US';
countries['CA'] = 'CA';

/**
 * Loads the multimap. Assumes the layer - mapviewer to be present in the UI. 
 */ 
function onLoad()
{	
	mmProperties = new MMProperties();
	
	if (! loadDealershipProperties() )
	{ 
		return;
	}
		
	// Check browser compatibility:
	if( MMIsSupportedBrowser() ) 
	{  
 		loadingStatus(true);		
 		initializeMapViewer();
		  
		//The dealer coords is enough to confirm that previous state is to be loaded 
		if ( areCoordinates ( linkDealerCoords ) ) // linkDealerCoords = "latitude,longitude"
		{
			loadState();
		}
		else
		{
            showDealership(true);
	 	} 		  		
 	}
}

function initializeMapViewer() 
{	
	mmProperties.mapviewer = new MultimapViewer( document.getElementById( 'mapviewer' ) );	
  if ( dealer.country.toUpperCase() == 'CA' )
  {
    mmProperties.mapviewer.setOption('units', 'km');
  }  
}
/**
 * update the map type labels
 */
function updateMapTypeLabels()
{
  var mapviewer = document.getElementById('mapviewer');
  updateElementsByClassName(mapviewer, 'a', 'MM_WORLD_MAP', arrStrings['apps.maps.type.world']);
  updateElementsByClassName(mapviewer, 'a', 'MM_WORLD_AERIAL', arrStrings['apps.maps.type.aerial']);
  updateElementsByClassName(mapviewer, 'a', 'MM_WORLD_HYBRID', arrStrings['apps.maps.type.hybrid']);
}

/**
 * This function is basically to enable loading of the widgets only after the map is loaded. This function should logically put in onLoad, but is put after 
 * every goToPosition/drawAndPositionMap. This is because geocoding is used which is asynchronous, and often the map loads after the onLoad 
 * terminates
 */
function addWidgets()
{
	// Add the Pan Zoom Widget (top, right, bottom, left):
	var topRight = new MMBox( 30, 20, undefined, undefined ); // Top left
	panzoomWidget = new MMPanZoomWidget( topRight );
	mmProperties.mapviewer.addWidget( panzoomWidget );
	  
	// Add Map type widget - {Map, Aerial, Hybrid}
	var topLeft = new MMBox (30, undefined , undefined, 11);
	var mapTypeWidget = new MMMapTypeWidget ( undefined, topLeft );
	mmProperties.mapviewer.addWidget( mapTypeWidget );  	 
	  
	// Add an overview widget:
	mmProperties.mapviewer.addWidget( new MMOverviewWidget ( undefined, new MMDimensions( 100, 100 ), undefined ) );  
    updateMapTypeLabels();
}

/**
 * Load the dealership location from printForm.dealerLocation.
 */
function loadDealershipProperties() 
{	
	if ( !arrLocations || !arrLocations[ document.forms['printForm'].elements['dealer.location'].value] ) 
		return false;
	fdDealerLocation = arrLocations[ document.forms['printForm'].elements['dealer.location'].value ];
	fdDealerLocation.country = countries[dealer.country.toUpperCase()];
	return true;
}

/**
 *	Load the previous state according to the querystring (data stored in variables of pattern link*)
 */

var mapCenter, mapZoomFactor; //These variables are specific to this and this function only!!!
function loadState() 
{						
	mmProperties.dealerLocation = getLocation( linkDealerDisplayName, linkDealerCoords );		
	mapCenter =  getLocation( undefined, linkMapCenter );
	mmProperties.userLocation = getLocation( linkUserDisplayName, linkUserCoords );	
	if ( !mapCenter ) mapCenter = mmProperties.dealerLocation;
	mapZoomFactor = linkMapZoomFactor;	
	mmProperties.mapviewer.setMapType( linkMapType );
	
	if ( linkIsRouteRequested && mmProperties.userLocation )
	{
		mmProperties.isReverse = linkIsReverse;
		loadLocations();
		
		funcRef = function() 
						{
							if ( !areRouteErrors() ) 
							{								
								addRoutePolyline();
								addEndMarkers(true);
								mmProperties.mapviewer.goToPosition( mapCenter, mapZoomFactor );		
								addWidgets(); 
								displayStages( mmProperties.route );
								collapseMap();    
							}
						}
		callRoute( funcRef );	// funcRef is the callback function. Once the route is called
								// multimap calls this function			
		
	}	
	else 
	{
		var marker = mmProperties.mapviewer.createMarker( mmProperties.dealerLocation, {'text': createDealerMarker(true)} );
		mmProperties.mapviewer.goToPosition( mapCenter, mapZoomFactor );		
		addWidgets(); 
		loadingStatus( false );    
	}
}

/**
 * Get the dealer location object 
 * @returns MMLocation location
 */
function getDealershipLocation ()
{
	var dealerAddress = new MMAddress();
	dealerAddress.street = fdDealerLocation.street;
	dealerAddress.city = fdDealerLocation.city;
	dealerAddress.state = fdDealerLocation.state;
	dealerAddress.zip = fdDealerLocation.zip;
	dealerAddress.country_code = fdDealerLocation.country;
	var location = new MMLocation();
	location.address = dealerAddress;
	return location;
}

/**
 *  Geocode the dealer location details for the latitude and longitude
 */
function showDealership(isOnload) {
    // Position it at the dealership, at zoom factor 15:
    
    if ( fdDealerLocation.isDefault && dealerDefaultCoordinates.latitude && dealerDefaultCoordinates.longitude )
    {
    	mmProperties.dealerLocation = getDealershipLocation();
    	mmProperties.dealerLocation.coords = new MMLatLon( dealerDefaultCoordinates.latitude, dealerDefaultCoordinates.longitude );
        isOnload == true ? displayDealer() : callRoute(resultsLoaded);
    }
    else 
    {
		var geocoder = new MMGeocoder(geoCodeDealer);		
		var address = new MMAddress();		
		address.qs =  getAddressAsString( getDealershipLocation().address );
		address.country_code = fdDealerLocation.country;		
		geocoder.geocode (address);
	}	  
}

/**
 * Call back method for getting the latitude and longitude information of the dealer's address
 */
function geoCodeDealer( loc, error_code ) 
{  	
	if ( !mmProperties.timeoutOccurred ) 
	{
		mmProperties.dealerLocation = getDealershipLocation();
		mmProperties.dealerLocation.coords = loc[0].coords;	
		if ( mmProperties.route && !mmProperties.route.error_code )
		{	
			loadLocations();
			callRoute(resultsLoaded);
		}
		else 
		{
			displayDealer();			
		}
	}
}
/**
 * Displays the dealer
 */
function displayDealer( )
{
	loadingStatus( false );   
	var marker = mmProperties.mapviewer.createMarker( mmProperties.dealerLocation, {'text': createDealerMarker(true) });
	setMapTitle();
	mmProperties.mapviewer.drawAndPositionMap( mmProperties.dealerLocation );
	addWidgets(); 	
}
/**
 * Set the map title
 */
function setMapTitle() 
{
	getRegions = function( location ) 
	{
		if (location != undefined && location.address != undefined )
		{
			var regions = "";
			
			regions += ( location.address.country_code )?(location.address.country_code + "/"):"";
			regions += ( location.address.state )?(location.address.state + "/"):"";
			regions += ( location.address.city )?(location.address.city + "/"):"";
			
			return regions.substring(0, regions.length-1).toUpperCase();
		}
		
	}
	document.getElementById( 'region' ).innerHTML = getRegions( mmProperties.dealerLocation ) ;
}


/**
 * Shows the position of the dealer on the map
 */
function createDealerMarker(createTooltip)
{	
	var markerText = "";	

	if ( createTooltip ) 
	{
		markerText += busname;
		markerText += ( fdDealerLocation.label )?('-' + fdDealerLocation.label):"";
		markerText = '<nobr>' + markerText + '</nobr>';
		markerText = ( brandIconIndex > 0 )?("<img src=\'" + vfsBase +"/apps/img/maps/icons/" + brandIconIndex + ".gif\' /><br />" + markerText):"";
		markerText = '<div>' + markerText + '</div>';
	}
	
	markerText = "<img src=\'" + vfsBase +"/apps/img/maps/dealer-location.gif\' />" + markerText;
	markerText = '<div class="marker" onmouseover="showTooltip(this);" onmouseout="hideTooltip(this);">' + markerText + '</div>';

	return markerText;
}

/**
 * Shows the position of the user on the map
 */

function createUserMarker(createTooltip) 
{
	var markerText = "";	

	markerText = ( createTooltip )?('<div><nobr>' + arrStrings['apps.maps.location.user.tooltip.text'] + '</nobr></div>'):"";
	markerText = "<img src=\'" + vfsBase +"/apps/img/maps/user-location.gif\' />" + markerText;
	markerText = '<div class="marker" onmouseover="showTooltip(this);" onmouseout="hideTooltip(this);">' + markerText + '</div>';

	return markerText;
}

/**
 * Disable form elements while mmviewer is retreiving data. 
 * @param bool true if the data is being loaded 
 */
function loadingStatus( bool ) 
{
	var statusDiv = document.getElementById('statusDiv');
	if (statusDiv) 
	{
		statusDiv.style.display = (bool)?'block':'none';
		statusDiv.style.visibility = (bool)?'visible':'hidden';						
		mmProperties.timeoutId = (bool)?( (mmProperties.timeoutId == undefined)?setTimeout( "terminateRequest()", mmProperties.timeoutInterval ):mmProperties.timeoutId  ):clearTimeout( mmProperties.timeoutId ); 		
		if ( bool ) resetMap();
		mmProperties.loading = bool;
		mmProperties.timeoutOccurred = false;
	}	
}

/**
 * Terminate the current request due to timeout 
 */
function terminateRequest()
{	
	loadingStatus( false );
	var head = document.getElementsByTagName( 'head' )[0];
	mmProperties.timeoutOccurred = true;
	alert( arrStrings['apps.maps.error.timeout'] ); 	
}

/**
 * Change the location of the dealer
 */ 
function changeDealerLocation ()
{
	loadDealershipProperties();
	mmProperties.mapviewer.removeAllOverlays();
    showDealership(false);
}
/**
 * Creates step marker
 */
function createStepMarker(location, instruction, text, zindex) 
{
    var marker = mmProperties.mapviewer.createMarker(location, {zIndex: zindex, 'text' : text});
    marker.setInfoBoxContent('<p>' + instruction + '</p>');
	return marker;
}  

/*****************************************
 * Did you mean ? Dialogue
 ******************************************/

function displayMultipleLocations( error ) 
{	
	document.getElementById( 'didyoumean.header' ).innerHTML = arrStrings['apps.maps.dialogue.didyoumean.header'];
	document.getElementById('userAddressMatches').style.display = 'block';

	var userLocationInner = document.getElementById('userLocationInner');
	var table = document.createElement('table');
	table.className = 'no-margin';	
	table.setAttribute( 'id', 'userLocationMatches' );
	userLocationInner.appendChild( table );
	
	var tbody = document.createElement( 'tbody' );
	table.appendChild( tbody );
	
	for (var j = 0; j < error.results.length; j++) 
	{
		var tr = document.createElement( 'tr' );
		tr.onmouseover = function() { this.style.bgColor = "#8DBDE8"; }
		tbody.appendChild( tr );
		
		var displayName = error.results[j].address.display_name;
		var point = error.results[j].coords; 
		
		var locTd = document.createElement('td');	
		locTd.className = 'location-name';				
		locTd.style.paddingRight = '20px';
		locTd.appendChild( document.createTextNode(displayName) );		
		locTd.setAttribute("id", point.lat + "," + point.lon);
		locTd.onclick = function () 
						{
							var latlon = this.getAttribute("id").split(',');
							var lat = latlon[0];
							var lon = latlon[1];									
							qs = this.childNodes[0].nodeValue;
							callRoute_userAddressMatches(lat, lon, qs); 
						}										
		
		var srNoTd = document.createElement( 'td' );
		srNoTd.appendChild(document.createTextNode((j+1)+". "));
		
		tr.appendChild( srNoTd );
		tr.appendChild( locTd );				
	}   
}      

/*****************************************
 * Calculating Route 
 ******************************************/

/**
 * Find the route 
 * @param funcRef - The callback function after route has been calculated   
 */
function callRoute ( funcRef ) 
{   
	if (! funcRef ) return;	
	loadingStatus( true );
    loadLocations();
	
	_funcRef = function() { if ( !mmProperties.timeoutOccurred ) { loadingStatus( false ); funcRef();  } }
	mmProperties.route_finder = new MMRouteRequester( _funcRef );	
	 
	cleanUp();
	cleanMultipleMatches();

	mmProperties.route = new MMRoute( mmProperties.locations );
	mmProperties.route.lang = userLanguage;		//Setting the current user language .

	mmProperties.route.optimize_for = 'time';
	mmProperties.route.mode = 'driving'; 
		
	mmProperties.route_finder.request( mmProperties.route );	
}

/** 
 * Load the source and the destination
 * @return location - Array of MMLocation containing the source followed by the destination 
 */
function loadLocations ()
{
	if ( mmProperties.dealerLocation && mmProperties.userLocation )
	{
		mmProperties.locations = new Array();
		if ( !mmProperties.isReverse )
		{
			mmProperties.locations.push( mmProperties.userLocation );
			mmProperties.locations.push( mmProperties.dealerLocation );
		}
		else 
		{
			mmProperties.locations.push( mmProperties.dealerLocation );
			mmProperties.locations.push( mmProperties.userLocation );
		}
	}
}

/**
 * Construct the user location from printForm.userLocation.text
 */
 
function callRoute_getDirection()  
{	
	validUserLocation = function ( strLocation ) 
	{		
		return !( (strLocation == "" )  || (strLocation == arrStrings['apps.maps.location.user.prompt'] ) );		
	}

	if ( mmProperties.dealerLocation && !mmProperties.loading )
	{		
		var strUserLocation = document.forms['printForm'].elements['userLocation.text'].value.trim();		
		
		if ( !validUserLocation( strUserLocation ) )
		{
			alert( arrStrings['apps.maps.error.address.invalid'] );
			return;
		}
		userAddress = new MMAddress();
		userAddress.qs = strUserLocation;		
		userAddress.country_code = fdDealerLocation.country; 
		mmProperties.userLocation = new MMLocation();
		mmProperties.userLocation.address = userAddress;
		
		mmProperties.isReverse = false;
		loadLocations();		
  				
		callRoute ( resultsLoaded );	
	}
}

/** 
 * Construct a user location from coordinates and find route
 */
function callRoute_userAddressMatches(lat, lon, qs) 
{	
	if ( lat && lon && qs && !mmProperties.loading ) 
	{
		document.forms['printForm'].elements['userLocation.text'].value = qs;
		var location = new MMLocation(new MMLatLon(lat, lon));
		var address = new MMAddress();
		address.qs = qs;
		location.address = address;
		mmProperties.userLocation = location;

		mmProperties.isReverse = false;		
		loadLocations();
		
		callRoute ( resultsLoaded );	
	}	
}

/**
 * Find the reverse route 
 */ 
function callRoute_reverse() 
{	
	
	if (! mmProperties.loading )
	{		
		mmProperties.isReverse = ( mmProperties.isReverse == false );
		loadLocations();
		callRoute ( resultsLoaded );		
	}	
}
   
/**
 * Clean previous results
 */   
function cleanUp () 
{
    var stepsContainer = document.getElementById( 'routeSteps' );
    var userAddressMatches = document.getElementById( 'userAddressMatches' );
    while (stepsContainer.firstChild) 
        stepsContainer.removeChild(stepsContainer.firstChild);
    
    stepsContainer.style.display = 'none';
    userAddressMatches.style.display = 'none';
    mmProperties.mapviewer.removeAllOverlays();
    mmProperties.markers = new Array();
}  

/**
 * Remove multiple matches generated by geocoding of user location during the route calculation 
 */
function cleanMultipleMatches() 
{
	var userLocationInner = document.getElementById( 'userLocationInner' );
	var userLocationTables = userLocationInner.getElementsByTagName( 'table' );
	if ( userLocationTables.length ) 
		for( var i=0; i<userLocationTables.length; i++ )
			userLocationInner.removeChild( userLocationTables[i] );			
}     

/**
 * Process after the route has been retrieved 
 */
function resultsLoaded () 
{
	
	if ( !areRouteErrors() ) 
	{		
		addRoutePolyline();
		displayStages( mmProperties.route );
		collapseMap();
		mmProperties.mapviewer.goToPosition( mmProperties.mapviewer.getAutoScaleLocation( mmProperties.route.bounds ) );				
		addEndMarkers(true);		    
	    loadingStatus( false );
	}
}

function areRouteErrors() 
{
	if (mmProperties.route.error_code) 
	{
       (mmProperties.route.error_code == 'MM_ROUTE_GEOCODING_ERRORS')?processGeocodingErrors (mmProperties.route.geocoding_errors):showErrors(arrStrings['apps.maps.error.multimap.header'], arrStrings['apps.maps.error.multimap.content']);       
		return true;
    }	
	return false;
}

function addRoutePolyline () 
{
		if (mmProperties.route.polyLine) 
		{
        for( var i = 0, l = mmProperties.route.polyLine.length; i < l; ++i ) 
        {
          //mmProperties.route.polyLine[i].reset(undefined, {'opacity':0.55, 'color':'#00FF00', 'thickness':2.2});
          mmProperties.mapviewer.addOverlay(mmProperties.route.polyLine[i]);
        }
	}
}

function addEndMarkers (createTooltip) 
{
	var dealerMarker = mmProperties.mapviewer.createMarker( mmProperties.dealerLocation, {'text': createDealerMarker(createTooltip)} );
	var userMarker = mmProperties.mapviewer.createMarker( mmProperties.userLocation, {'text': createUserMarker(createTooltip)} );
}



function displayStages( route ) 
{
    var curr_step = 1;
    var stages = route.stages; 
    var container = document.getElementById('routeSteps');

    var divRouteSummary = document.createElement('div');
	divRouteSummary.className="route-summary";
	divRouteSummary.setAttribute("id", "route-summary");
	
	divRouteSummary.appendChild( createRouteSummaryTable( mmProperties.locations, mmProperties.isReverse ) );
   
    container.appendChild(divRouteSummary);		
	
	var routeDetails = document.createElement('div');
	routeDetails.setAttribute('id', 'routeDetails');
	routeDetails.className = "route-details";		
	routeDetails.appendChild( createRouteStepsTable( route ) );	   	
	container.appendChild( routeDetails );  
	
	container.style.display = "block";
}

function createRouteSummaryTable( locations, isReverse ) 
{	
	var table = document.createElement( 'table' );
	table.className="no-margin";
	var tbody = document.createElement( 'tbody' );
	table.appendChild( tbody );	
	
	var trFrom = document.createElement( 'tr' );
	var tdImageInPrint = document.createElement( 'td' );
	var tdHeader = document.createElement( 'td' );
	var tdImageOnScreen = document.createElement( 'td' );
	var tdAddress = document.createElement( 'td' );
	
	tdImageInPrint.className = 'noScreen';
	tdHeader.className = 'summaryHeader';
	tdImageOnScreen.className = 'noPrint summaryImage';
	tdAddress.className = 'address';
		
	trFrom.appendChild( tdImageInPrint );
	trFrom.appendChild( tdHeader );
	trFrom.appendChild( tdImageOnScreen );
	trFrom.appendChild( tdAddress );
	
	var trTo = trFrom.cloneNode( true );
	
	var srcImageFrom, srcImageTo;

	if (!isReverse) 
	{	
		srcImageFrom = vfsBase +'/apps/img/maps/user-location.gif';
		srcImageTo = vfsBase + '/apps/img/maps/dealer-location.gif';
	} 
	else 
	{
		srcImageFrom = vfsBase +'/apps/img/maps/dealer-location.gif';
		srcImageTo = vfsBase + '/apps/img/maps/user-location.gif';
	}	

	trFrom.childNodes[0].innerHTML = '<img src="' + srcImageFrom + '" />';	
	trFrom.childNodes[1].innerHTML = arrStrings['apps.maps.summary.from'];	
	trFrom.childNodes[2].innerHTML = '<img src="' + srcImageFrom + '" />';		
	trFrom.childNodes[3].innerHTML = getAddressAsString( locations[0].address );

	trTo.childNodes[0].innerHTML = '<img src="' + srcImageTo + '" />';		
	trTo.childNodes[1].innerHTML = arrStrings['apps.maps.summary.to'];	
	trTo.childNodes[2].innerHTML = '<img src="' + srcImageTo + '" />';		
	trTo.childNodes[3].innerHTML = getAddressAsString( locations[1].address );			
	
	tbody.appendChild( trFrom );
	tbody.appendChild( trTo );
	
	return( table );
}


function createRouteStepsTable( route )
{
	var curr_step = 1;
    var stages = route.stages;
	var routeStepCount = 1;
	
	var tableBody = '<tbody>';
	tableHead = '<tr class="noScreen"><td class="routeDetailsHeader"></td><td class="routeDetailsHeader">Travel Directions</td><td  class="routeDetailsHeader"></td><td class="routeDetailsHeader">For</td></tr>';
	tableBody += tableHead;	
	
	/* Based on the isReverse condition, we can have the user lat and lon */
	if ( !mmProperties.isReverse ) /* User is start */
	{
		mmProperties.userLocation.coords = stages[0].steps[0]['start_point'];
	}
	else 
	{
		var lastStage = stages[stages.length - 1].steps;
		mmProperties.userLocation.coords = lastStage[lastStage.length - 1]['end_point'];
	}
    
    for (var count=0; count < stages.length; count++) 
	{
        var steps = stages[count].steps;

        for (var stepCount=0; stepCount < steps.length; stepCount++) {			
            var text = curr_step;
            var zindex = mmProperties.MAX_Z_INDEX - curr_step + 1;
            if (count == stages.length - 1 && stepCount  == steps.length - 1) 
            {
                zindex = mmProperties.MAX_Z_INDEX; 
            }  
			          
            var instruction = (getBrowserName()=="Microsoft Internet Explorer")?decodeURIComponent ( escape (steps[stepCount].instruction) ): steps[stepCount].instruction;
            var roadname = steps[stepCount].road_name;
            var roadnumber = steps[stepCount].road_number; 
			var lat = steps[stepCount]['start_point'].lat;
			var lon = steps[stepCount]['start_point'].lon;			

            if (roadname && roadnumber && roadname!=roadnumber) 
            {
                instruction += ' <span class="route-step-road">' + roadname + ' (' + roadnumber + ') </span>';
            } 
            else if (roadname) 
            {
                instruction += '<span class="route-step-road"> ' + roadname + ' </span>';
            } 
            else if (roadnumber) 
            {
                instruction += ' <span class="route-step-road">' + roadnumber + ' </span>';				
            }	
            		            
            var distance = '';
			var _distance = '';
            if (steps[stepCount].distance.miles > 0) { _distance += '' + steps[stepCount].distance.miles + ' mile(s) (' + steps[stepCount].distance.km + ' km)'; }
            if (_distance != '') { distance = '<div class="noPrint">for ' + _distance + '</div>';};
            var tr = '<tr class="not-highlighted" name="route-step" id="route-step-'+routeStepCount+'" onclick="highlight(\'route-step-'+routeStepCount+'\');goToPosition('+lat+','+lon+');showMarker(' + routeStepCount + ')">';
						
			var countTd = '<td class="route-step-number">' + routeStepCount + '</td>';
			var td = '<td class="route-step">' + instruction + distance + '</td>';
			var srcImgDirection = vfsBase +'/apps/img/maps/';
			
			if ((count==0 && stepCount==0) || (count==(stages.length-1) && (stepCount==steps.length-1)))
			{
				srcImgDirection += 'dir_o.gif';
			}
			else if (steps[stepCount].turn_direction=='R' || steps[stepCount].turn_direction=='L')
			{
				srcImgDirection += 'dir_'+ steps[stepCount].turn_direction.toLowerCase() + '.gif';
			}
			else if (steps[stepCount].instruction.indexOf('Continue')!=-1)
			{
				srcImgDirection += 'dir_a.gif';
			}
			else if (steps[stepCount].instruction.indexOf('roundabout')!=-1)
			{
				srcImgDirection += 'dir_ra.gif';
			}
			else
			{ 
				srcImgDirection += 'dir_null.gif';
			}
			
			var imgTd = '<td class="route-step-image column-right"><img src="' + srcImgDirection + '" /></td>';
			
			var printDistance = '<td class="route-step-distance">' + _distance + '</td>';
			
			tr += countTd + td + imgTd + printDistance + '</tr>';			
            tableBody += tr;
			
			/* The start and the end states are dealer location and user location, so we don't put markers over here */			
			if ( !( (count == 0 && stepCount  == 0)  || (count == stages.length - 1 && stepCount  == steps.length - 1) ) )
			{
                mmProperties.markers[ routeStepCount ] = createStepMarker(steps[stepCount].start_point, instruction, text, zindex);            
				mmProperties.markers[ routeStepCount ].setVisibility( false );			
            }        			
            
            ++routeStepCount;
            ++curr_step;
        }
	}	
	tableBody += '</tbody>';		
	var tableColumns = '<colgroup span="4"><col /><col /><col /><col /></colgroup>';
	var tableInnerHTML = '<table class="mapsTable no-margin">' + tableColumns + tableBody + '</table>';
	var tableEnvelope = document.createElement( 'div' )
	tableEnvelope.innerHTML = tableInnerHTML;
	return tableEnvelope;
}

function processGeocodingErrors (errors) 
{
    for (var i = 0; i < errors.length; i++) 
	{
        (errors[i].error_code == 'MM_GEOCODE_NO_MATCHES')?showErrors ( arrStrings['apps.maps.error.address.notfound.header'], arrStrings['apps.maps.error.address.notfound.content'] ):displayMultipleLocations( errors[i] );        
    }
	loadingStatus( false );
}

function showErrors ( header, content )
{
	document.getElementById( 'didyoumean.header' ).innerHTML = header;
	var table = document.createElement('table');
	var tbody = document.createElement('tbody');
	var tr = document.createElement('tr');
	var td = document.createElement('td');
	td.appendChild( document.createTextNode ( content ) );
	tr.appendChild( td );
	tbody.appendChild( tr );
	table.appendChild( tbody );
	document.getElementById( 'userLocationInner' ).appendChild( table );
	document.getElementById('userAddressMatches' ).style.display = 'block';
} 

function highlight(layer)
{	
	/* Patch for the unavailability of document.getElementsByName in ie */
	var getElementsByName_iefix = function(tag, name) 
	{     
	    var elem = document.getElementsByTagName(tag);
	    var arr = new Array();
	    for(i = 0,iarr = 0; i < elem.length; i++) 
		{
	        att = elem[i].getAttribute("name");
	        if(att == name) 
			{
	            arr[iarr] = elem[i];
	            iarr++;
	        }
	    }
		return arr;
	}
	 
	var routeSteps = getElementsByName_iefix('tr', 'route-step');
	for (i=0;i<routeSteps.length;i++)
		routeSteps[i].className="not-highlighted";
	document.getElementById(layer).className="highlighted";	
}



/*
 * Page functions 
 */
 
function printPage() 
{		
	if ( mmProperties.loading )	return;
	closeMapDialogues();
	if ( !mmProperties.route || mmProperties.route.error_code )
	{
		createPrintPage( 'standard' );
	}
	else
	{	
		document.getElementById( 'print-dialogue' ).style.display='block';
	}		
}

function createPrintPage( printMode )
{	
	document.getElementById( 'print-dialogue' ).style.display='none';
	if ( printMode != 'standard' && printMode != 'detailed' ) return;
	var queryString = getPageQueryString();
	queryString += getQuery( '_flowExecutionKey', document.forms['printForm'].elements[ '_flowExecutionKey' ].value )
				+  getQuery( '_eventId', 'printMap' )
				+  getQuery( 'printMode', printMode );	
				+  getQuery( 'mapType', mmProperties.mapviewer.getMapType() );
	queryString = queryString.substring( 0, queryString.length - 1 );
	
	var popUpWin = window.open( location.href.split('?')[0] + '?' + queryString,'_blank' );
	
	if(!popUpWin) 
	{
	  alert("You may be using a popup blocker. Please disable it to view print page.");
	  return;
	}	
}

function getPageLink()
{
	if ( mmProperties.loading )	return;
	closeMapDialogues();
	var queryString = location.href.split('?')[0] + '?' + getPageQueryString();
	queryString = queryString.substring( 0, queryString.length - 1 );
	document.getElementById( 'dialogueLink' ).innerHTML = '<nobr>' + queryString + '</nobr>';
	document.getElementById( 'link-dialogue' ).style.display='block';	
}

function closeMapDialogues()
{
	document.getElementById( 'link-dialogue' ).style.display = 'none';
	document.getElementById( 'print-dialogue' ).style.display = 'none';
}


/*
 * Map drag  to expand and collapse
 */

var isMapCollapsed = false;

function toggleMap()
{
	mapStateChange( isMapCollapsed, true );
}

function expandMap()
{
	mapStateChange( true, true );
}

function resetMap()	//A version of expand map, where the drag button is not shown 
{
	mapStateChange( true, false );
}

function collapseMap()
{
	mapStateChange( false, true );
}

function mapStateChange( isCollapsed, showDrag )
{
	var layerMapDrag = document.getElementById( 'map-drag' );
	var mapColumn = document.getElementById( 'map-column' );
	var routeStepsColumn = document.getElementById( 'route-steps-column' );	

	if ( mmProperties.route )
	{
		layerMapDrag.innerHTML = (isCollapsed)?'<img src="' + vfsBase + '/apps/img/maps/map-collapse.gif" title="expand" />':'<img src="' + vfsBase + '/apps/img/maps/map-expand.gif" title="expand" />';		
		layerMapDrag.style.visibility = (showDrag)?'visible':'hidden';
	}
	
	
	mapColumn.className = (isCollapsed)?'map-full-width':'map-collapse';
	routeStepsColumn.className = (isCollapsed)?'route-steps-collapse':'route-steps-show';		
	isMapCollapsed = !( isCollapsed );
  if (mmProperties.mapviewer) mmProperties.mapviewer.resize();
}

/*
 * Utility Functions 
 */
 
//  Somehow the MMAddress#toString() wasn't working properly!

function getAddressAsString(address)
{	
	if (address.qs) return address.qs;
	strAddress = '';
	strAddress += (address.street?(address.street+', '):'');
	strAddress += (address.city?(address.city+', '):'');
	strAddress += (address.state?(address.state+', '):'');
	strAddress += (address.zip?(address.zip+', '):'');
	return strAddress.substring( 0, strAddress.length-2 );
}
 
function getPageQueryString()
{
	if ( mmProperties.loading ) 
		return;
	var printForm = document.forms[ 'printForm' ];

	if ( !printForm )
	{
		//No printform present		
		return;
	}
	
	/* Dealer Location */	
	var queryString = getQuery( 'dealerLocation.displayName', getAddressAsString( mmProperties.dealerLocation.address ) )
					+ getQuery( 'dealerLocation.latitude',  mmProperties.dealerLocation.coords.lat ) 
					+ getQuery( 'dealerLocation.longitude', mmProperties.dealerLocation.coords.lon );
	
	if ( mmProperties.userLocation != undefined )
	{
		/* User Location */		
		queryString += getQuery( 'userLocation.displayName', getAddressAsString( mmProperties.userLocation.address ) );
		if ( mmProperties.userLocation.coords )
		{
			queryString += getQuery( 'userLocation.latitude',  mmProperties.userLocation.coords.lat ) 
						 + getQuery( 'userLocation.longitude', mmProperties.userLocation.coords.lon );
		}		
	}
		
	/* Map Details */
	queryString += getQuery( 'mapZoomFactor', mmProperties.mapviewer.getZoomFactor() );	
	
	var mapCenter = mmProperties.mapviewer.getMapBounds().getCenter();
	queryString += getQuery( 'mapCenter.latitude', mapCenter.lat ) 
				+  getQuery( 'mapCenter.longitude', mapCenter.lon ) ;
	
	queryString += getQuery( 'mapType', mmProperties.mapviewer.getMapType() );
	
	/* Route Details */
	
	if ( mmProperties.route && !mmProperties.route.error_code )
	{
		queryString += getQuery( 'isRouteRequested', true )
					+  getQuery( 'isReverse', mmProperties.isReverse );
	}	
	
	return queryString;	
}

function getQuery(name, value ) 
{
	return ( name + '=' + encodeURIComponent( value ) + '&' );
}

function goToPosition(lat, lon)
{
	mmProperties.mapviewer.drawAndPositionMap(new MMLocation(new MMLatLon(lat, lon)));	
}

function showMarker( markerNo )
{
	if ( mmProperties.markers[ markerNo ]  )
	{
		mmProperties.markers[ markerNo ].setVisibility( true );
	}
}

function showTooltip(layer)
{	
	changeToolTipStatus( layer, false );		
}

function hideTooltip(layer)
{	
	changeToolTipStatus( layer, true );
}

function findPos(obj) 
{		
	if (obj.offsetParent) 
	{
		var coords = new Object;
		coords.x = obj.offsetLeft;
		coords.y = obj.offsetTop;
		while (obj = obj.offsetParent) 
		{
			coords.x += obj.offsetLeft;
			coords.y += obj.offsetTop;
		}
	}
	return coords;
}

function changeToolTipStatus( layer, hide ) 
{
	var coords = findPos( layer );	
	var tooltip = getTooltips(layer)[0];
		
	if ( tooltip )
	{
		if ( coords )
		{			
			with(tooltip.style)
			{
				bottom = top = right = left = '';
			}
			(coords.y>340)?(tooltip.style.bottom ='2em'):(tooltip.style.top='2em');		
			(coords.x>614)?(tooltip.style.right = '2em'):(tooltip.style.left='2em');
	}
		tooltip.style.display = (hide)?'none':'block';
		tooltip.style.visibility = (hide)?'hidden':'visible';		
}
}

function getTooltips (layer)
{
	return ( layer.getElementsByTagName('div') );
}

function getLocation ( displayName, coords )  //Helper function to extract location object from a string and comma seperated coords
{
	if ( ( displayName == '' ) && !areCoordinates( coords ) ) return null; 
		
	var location = new MMLocation();
	var arrCoords = coords.split(',');
	if (arrCoords.length == 2 && areCoordinates( coords ) ) 
	{
		location.coords = new MMLatLon( arrCoords[0], arrCoords[1] );							
	}
	
	if ( displayName != undefined )
	{
		var address = new MMAddress();
		address.qs = displayName;
		location.address = address;
	}				
	
	return location;
}

function areCoordinates( coords ) 
{
	if ( !coords ) return false;
	var arrCoords = coords.split( ',' );
	return ( arrCoords.length == 2 && arrCoords[0] != '' && arrCoords[1] != '' );
}

function updateElementsByClassName(oElm, strTagName, strClassName, strNewLabel)
{
  var arrElements = oElm.getElementsByTagName(strTagName);
  var oElement;
  for(var i=0; i<arrElements.length; i++)
  {    
    oElement = arrElements[i];
    if(oElement.className.indexOf(strClassName)!=-1)
    {
      oElement.innerHTML = strNewLabel;
    }
  }
  return;
}

