
window.travelShopResultFieldNames = [ 'name', 'street', 'town','pc', 'lat', 'lon', 'open_mon', 'open_tue', 'open_wed', 'open_thu', 'open_fri', 'open_sat', 'open_sun', 'store_fx', 'telephone' ];

window.travelShopsMapViewer = null;
window.travelShopsMapSearcher = null;
window.travelShopsMapMarkers = [];



// called when page first loaded
function travelShopsInitialize() {
	// create the map viewer on the page and set its start position
    window.travelShopsMapViewer = new MultimapViewer( $( "TravelShopsFinderMapViewer" ) );
    window.travelShopsMapViewer.goToPosition( new MMLocation( new MMLatLon( 51.518235, -0.111258 ) ,15 ) );
	
	// add a pan/zoom widget to the map
	window.travelShopsMapViewer.addWidget( new MMPanZoomWidget() );
	
    travelShopsSetLoadingStatus( false );
}



// change the page display while a search is in progress
function travelShopsSetLoadingStatus( isLoading ){
    // disable the form elements while loading
	$( "TravelShopsFinderPostcode" ).disabled = isLoading;
	$( "TravelShopsFinderLimit" ).disabled = isLoading;
	$( "TravelShopsFinderSubmit" ).disabled = isLoading;

	// show or hide the progress indicator while loading
	$( "TravelShopsFinderLoadingIndicator" ).style.display = isLoading ? "block" : "none";
	
	// make sure Firefox updates its display
	firefoxForceRerender();
}



// perform a travel shop search using the parameters provided by the user
function travelShopsSearch(){
	if( window.travelShopsMapViewer == null ){ return; }
	
	$( "TravelShopsFinderSearchResultsIntro" ).style.display = "none";
    travelShopsClearSearchResults();
	
	var searchResponseHandler = travelShopsResultsReceived;
    window.travelShopsMapSearcher = new MMSearchRequester( searchResponseHandler );
	
    var search = new MMSearch(); 
    search.return_fields = window.travelShopResultFieldNames;
    search.radius_units = "miles";
    search.route_modes = "walking,driving";   

	// get the values of the input fields used to control the search
	var postcode = $F( "TravelShopsFinderPostcode" );
	var countryCode = $F( "TravelShopsFinderCountryCode" );
    var maxDistance = $F( "TravelShopsFinderLimit" );
	
	// if the user supplied a postcode
	if( postcode != "" ){
		// then tell the search to use that address
		search.address = new MMAddress( { qs: postcode, country_code: countryCode } );
	} else {
		// otherwise, just search from where the map viewer is currently looking
        search.point = window.travelShopsMapViewer.getCurrentPosition(); 
	}

	// also configure the maximum distance for the search, if the user specified one
    if( maxDistance != "" ){
        search.max_distance = Number( maxDistance );
    }

	// configure the other search options based on hidden field values on the page
	search.count = Number( $F( "TravelShopsFinderCount" ) );
	search.start_index =  Number( $F( "TravelShopsFinderStartIndex" ) );
    search.order_by_fields = $F( "TravelShopsFinderOrderByFields" );
    search.order_by_order = $F( "TravelShopsFinderOrderByOrder" );
    search.result_set_size = Number( $F( "TravelShopsFinderResultSetSize" ) );

    travelShopsSetLoadingStatus( true );
	
	// start the search
    window.travelShopsMapSearcher.search( search );
}  



// remove any existing search results from the map and the link list
function travelShopsClearSearchResults(){
	window.travelShopsMapViewer.removeAllOverlays();
	window.travelShopsMapMarkers = [];

	// remove any existing links from the list
	var linkList = $( "TravelShopsFinderSearchResultLinks" );
	if( linkList != null ){
		removeAllChildNodes( linkList );
	}
}



// collect all the records from the returned recordsets into a single list of records
function travelShopsCollectReturnedRecords( searcher ){
	var returnedRecords = [];

	// run through each recordset
    for( var i = 0; i < searcher.record_sets.length; i++ ) {
		var recordSet = searcher.record_sets[i];

        if( recordSet.records ){
            for( var j = 0; j < recordSet.records.length; j++ ){
                var record = recordSet.records[j];                  

				returnedRecords.push( record );
            }
        }
    }

	return returnedRecords;
}



// update the search result links to match the returned records
function travelShopsUpdateSearchResultLinks( returnedRecords ){
	var linksDiv = $( "TravelShopsFinderSearchResultLinks" );
	var noResultsMessage = $( "TravelShopsFinderSearchResultsNone" );
	if( (linksDiv == null) || (noResultsMessage == null) ){ return; }
	
	// remove any existing content from the links DIV
	removeAllChildNodes( linksDiv );
	
	if( returnedRecords.length > 0 ){
		var table = '';
	
		table += '<table>';
		for( i = 0; i < returnedRecords.length; i++ ){
			var record = returnedRecords[i]
			var markerNumber = i + 1;
			
			table += '<tr>';
			table += '<th>' + markerNumber + '.</th>';
			table += '<td><a href="#" onclick="travelShopsShowMarker('+ i + ');return false;">' + record.name + '</a></td>';
			table += '</tr>';
		}
		
		table += '</table>';

		Element.update( linksDiv, table );
		
		// show the list and hide the no results message
		linksDiv.style.display = "block";
		noResultsMessage.style.display = "none";
	} else {
		// hide the list and show the no results message
		linksDiv.style.display = "none";
		noResultsMessage.style.display = "block";
	}
	
	// make sure Firefox updates its display
	firefoxForceRerender();
}



// show or hide the info box for the corresponding map marker
function travelShopsShowMarker( markerIndex ){
	// find the corresponding marker and display or hide its info box
	var marker = window.travelShopsMapMarkers[markerIndex];
	if( !marker ){ return; }

    if( marker.infoBoxOpened() ){
        marker.closeInfoBox();
    } else {
		marker.openInfoBox();
	}

}


// put a new marker on the map using information contained within a record
function travelShopsBuildMarker( record, markerNumber ){

	// if the record doens't have a position then we can't put a marker on the map
	if( !record.point ){ return; }

	// make some new nodes to hold the popup tab content
	var addressTabContent = document.createElement( "div" );
	var openingHoursTabContent = document.createElement( "div" );
	var distanceTabContent = document.createElement( "div" );

	addressTabContent.className = "travelShopsRecordTab";
	openingHoursTabContent.className = "travelShopsRecordTab";
	distanceTabContent.className = "travelShopsRecordTab";
	
	// format the title to appear at the top of each of the tabs
	var markerTitle = "#" + markerNumber + " " + record.name;
	new Insertion.Bottom( addressTabContent, '<div class="travelShopsRecordName">' + markerTitle + '</div>' );
	new Insertion.Bottom( openingHoursTabContent, '<div class="travelShopsRecordName">' + markerTitle + '</div>' );
	new Insertion.Bottom( distanceTabContent, '<div class="travelShopsRecordName">' + markerTitle + '</div>' );
	
	// fill in the address tab content
	var address = record.street + "<br/>" + record.town + "<br/>" + record.pc;
	new Insertion.Bottom( addressTabContent, '<div class="travelShopsRecordAddress">' + address + '</div>' );
	var hasBureauDeChange = ((record.store_fx == "Y") || (record.store_fx == "y")) ? "Yes" : "No";
	new Insertion.Bottom( addressTabContent, '<div class="travelShopsRecordBureauDeChange">Bureau de change: ' + hasBureauDeChange + '</div>' );
	new Insertion.Bottom( addressTabContent, '<div class="travelShopsRecordTelephone">Telephone: ' + record.telephone + '</div>' );
	
	// fill in the opening hours tab content
	var openingHours = '';
	openingHours += '<table>';
	openingHours += '<tr><th>Monday:</th><td>' + record.open_mon + '</td></tr>';
	openingHours += '<tr><th>Tuesday:</th><td>' + record.open_tue + '</td></tr>';
	openingHours += '<tr><th>Wednesday:</th><td>' + record.open_wed + '</td></tr>';
	openingHours += '<tr><th>Thursday:</th><td>' + record.open_thu + '</td></tr>';
	openingHours += '<tr><th>Friday:</th><td>' + record.open_fri + '</td></tr>';
	openingHours += '<tr><th>Saturday:</th><td>' + record.open_sat + '</td></tr>';
	openingHours += '<tr><th>Sunday:</th><td>' + record.open_sun + '</td></tr>';
	openingHours += '</table>';
	new Insertion.Bottom( openingHoursTabContent, '<div class="travelShopsRecordOpeningHours">' + openingHours + '</div>' );

	// fill in the distance tab content
    var distanceText = '';  
    if( record.distance ){
		distanceText += '<div class="travelShopsRecordDistance">';
        distanceText += '<strong>Straight line: <' + '/strong>' + record.distance.km + 'km (' + record.distance.miles + ' miles)';
		distanceText += '</div>';
    }

    if( record.driving_distance ){
		distanceText += '<div class="travelShopsRecordDistance">';
        distanceText +=  '<strong>Driving: <' + '/strong>' + record.driving_distance.km + 'km (' + record.driving_distance.miles + ' miles)';
        distanceText += '<br ' +'/><strong>Estimated Time: <' + '/strong>';
        distanceText += travelShopsFormatDuration( record.driving_duration );
		distanceText += '</div>';
    }
	
    if( record.walking_distance ){
		distanceText += '<div class="travelShopsRecordDistance">';
        distanceText += '<strong>Walking: <' + '/strong>' + record.walking_distance.km + 'km (' + record.walking_distance.miles + 'miles)';
        distanceText += '<br ' +'/><strong>Estimated Time: <' + '/strong>';
        distanceText += travelShopsFormatDuration( record.walking_duration );
		distanceText += '</div>';
    }

	new Insertion.Bottom( distanceTabContent, distanceText );

	// get the record location and create a new marker there
	var location = new MMLatLon( record.point.lat, record.point.lon );
	var marker = window.travelShopsMapViewer.createMarker( location, { "text" : markerNumber } );

	// popuplate the marker tabs
	var markerTabs = [
		new MMInfoBoxTab( "Address", addressTabContent ),
		new MMInfoBoxTab( "Opening Hours", openingHoursTabContent ),
		new MMInfoBoxTab( "Distance", distanceTabContent ),
	];
	marker.setInfoBoxContent( markerTabs );

	// keep a note of the marker in our global list of markers
    window.travelShopsMapMarkers.push( marker );
}



// create all the map markers for returned search records
function travelShopsUpdateMarkers( returnedRecords ){
	for( var i = 0; i < returnedRecords.length; i++ ){
		var markerNumber = i + 1;
		travelShopsBuildMarker( returnedRecords[i], markerNumber );
	}
}



// called when the results of a search are returned
function travelShopsResultsReceived(){
	var searcher = window.travelShopsMapSearcher;

	// update the display to show that we're no longer awaiting results
    travelShopsSetLoadingStatus( false );

	// deal with errors encountered during searching
    if( searcher.error_code ){
        if( searcher.error_code == "MM_GEOCODE_NO_MATCHES" ){
            alert( "No matches could be found for your input address." );
        } else {
            alert( searcher.error_code + ': ' + searcher.error_explanation );
        }       
        return;
    } 

	// extract all the records from any returned record sets
	var returnedRecords = travelShopsCollectReturnedRecords( searcher );

	travelShopsUpdateMarkers( returnedRecords );
	travelShopsUpdateSearchResultLinks( returnedRecords );

	// if we got some results back from the search then change the map
	// zoom and pan so that the markers are visible
    if ( returnedRecords.length > 0 ){
		// choose the best map view for the markers
		var bestMapViewPosition = window.travelShopsMapViewer.getAutoScaleLocation( window.travelShopsMapMarkers );
        window.travelShopsMapViewer.goToPosition( bestMapViewPosition ); 
     }

}



// format Integer to specified width (adding leading zeros)
function travelShopsPadInt( num, min_width ){
	var str = num.toString();
	while( str.length < min_width ){
		str = '0' + str;
	} 
	return str;
}



// format a duration into "dd:hh:mm" (days, hours, minutes)
function travelShopsFormatDuration( duration ){
	var result = "";
	result += travelShopsPadInt( duration.days, 2 ) + ":";
	result += travelShopsPadInt( duration.hours, 2 ) + ":";
	result += travelShopsPadInt( duration.minutes, 2 );

	return result;
}


MMAttachEvent( window, 'load', travelShopsInitialize );

