<html><head>
   <title>Bing Maps - v7.0</title>
<script type="text/javascript" src="https://www.bing.com/api/maps/mapcontrol/?branch=experimental&amp;callback=renderMap" defer="" async=""></script> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
  var BING_KEY = 'Ah8sxQqZmEO3u8cJ-ZvZi0gZWVmj2IvRZLBcY2R8FFfTOlRe5SeVlhJpDN2ny5fV';
  var map;
  var directionsManager;
  var timer;
  var load_up_timer;
  var global_use_dest_geo_codes = false;
    

	$( document ).ready(function() {
		
		load_up_timer = window.setInterval(function() {
			load_up_directions();
		}, 1000);
		
	});

  function load_up_directions() {
	clearInterval(load_up_timer);
	renderMap();

	if ((window.parent.Xrm.Page.getAttribute("btsss_facilitylatitude").getValue()) && (window.parent.Xrm.Page.getAttribute("btsss_facilitylongitute").getValue()))
	{
		calcDirectionsByAddress(true);
	}
	else
	{
		calcDirectionsByAddress(false);
	}
  }
  

  function loadHomeAndDestAddresses() {
	//pull values of the 5 to address fields and place them in variables
	var line1 = window.parent.Xrm.Page.getAttribute("btsss_addresstomileage").getValue();
	var line2 = window.parent.Xrm.Page.getAttribute("btsss_address2tomileage").getValue();
	var city = window.parent.Xrm.Page.getAttribute("btsss_addresstocitymileage").getValue();
	var state = window.parent.Xrm.Page.getAttribute("btsss_addresstostatemileage").getValue();
	var zip = window.parent.Xrm.Page.getAttribute("btsss_addresstozipmileage").getValue();
    var val_btsss_facilityaddress;
    var val_btsss_beneficiaryaddress;

	val_btsss_facilityaddress = (line1 || "") + " " + (line2 || "") + " " + (city || "") + " " + (state || "") + " " + (zip || "");
	
	window.parent.Xrm.Page.getAttribute("btsss_facilityaddress").setValue(val_btsss_facilityaddress);
	
	//pull values of the 5 from address fields and place them in variables
	var line1from = window.parent.Xrm.Page.getAttribute("btsss_addressfrommileage").getValue();
	var line2from = window.parent.Xrm.Page.getAttribute("btsss_address2frommileage").getValue();
	var cityfrom = window.parent.Xrm.Page.getAttribute("btsss_addressfromcitymileage").getValue();
	var statefrom = window.parent.Xrm.Page.getAttribute("btsss_addressfromstatemileage").getValue();
	var zipfrom = window.parent.Xrm.Page.getAttribute("btsss_addressfromzipmileage").getValue();
	
	val_btsss_beneficiaryaddress = (line1from || "") + " " + (line2from || "") + " " + (cityfrom || "") + " " + (statefrom || "") + " " + (zipfrom || "");
	
	window.parent.Xrm.Page.getAttribute("btsss_beneficiaryaddress").setValue(val_btsss_beneficiaryaddress);
  }
  // Create the map and calculate directions
  function renderMap() {
    // Configure Map Options
    var mapOptions = {
      credentials: BING_KEY,
      disablePanning: true,
      disableZooming: true,
      showLocateMeButton: false,
      zoom: 15,
      showMapTypeSelector: false
    };

    // Render the map
    map = new Microsoft.Maps.Map('#bingMap', mapOptions);
  }

  
    function AddBINGErrorMsg(bing_obj, msg)
	{
		if (bing_obj.errors.length > 0)
		{
			bing_obj.errors = bing_obj.errors + "," + msg;
		}
		else
		{
			bing_obj.errors = msg;
		}
	}
  
	function ValidateAddressAgainstBING(bingDataObj) {
		var func_result = false;
		
		//check user has entered something first
		if (bingDataObj.TargetAddress.length > 0) {
			//send location query to bing maps REST api
			var url = 'https://dev.virtualearth.net/REST/v1/Locations?query=' + bingDataObj.TargetAddress + '&key=' + BING_KEY + '&jsonp=?';
			
			$.getJSON(url, function (json_result) {
				var bBINGCallCompleted = (json_result) && 
										(json_result.resourceSets) && 
										(json_result.resourceSets.length > 0) && 
										(json_result.resourceSets[0].resources) && 
										((json_result.resourceSets[0].resources).length > 0);
				if (bBINGCallCompleted){
					
					if (json_result.resourceSets[0].estimatedTotal > 0) {
						
						if (json_result.resourceSets[0].resources[0].confidence == 'High')
						{
							func_result = true;
						}
						else
						{
							err_msg = "BING cannot find the address: " + bingDataObj.TargetAddress + 
										'. ' +
										"Closest address found is: " + json_result.resourceSets[0].resources[0].address.formattedAddress;
										
							AddBINGErrorMsg(bingDataObj, err_msg);
						}
					}					
					else {
						AddBINGErrorMsg(bingDataObj, "Provided address cannot be found: " + bingDataObj.TargetAddress);
					}
				}
				else {
						AddBINGErrorMsg(bingDataObj, "Unknown error for the address");
				}
				
				bingDataObj.AddressValidationCompleted = true;
				bingDataObj.valid_address = func_result;
			});
		}
		else {
			//window.parent.Xrm.Page.ui.setFormNotification("Please enter an address.", "ERROR", '3');
			AddBINGErrorMsg(bingDataObj, "Please enter an address.");
		}
	}
	
	function GetDirectionsFromBING(from_bing_data_obj, to_bing_data_obj) {
	  clearInterval(timer);

	  if ((from_bing_data_obj.valid_address == true) && (to_bing_data_obj.valid_address == true))
	  {
		  //FROM
		  var home = new Microsoft.Maps.Directions.Waypoint({
			address: from_bing_data_obj.TargetAddress,
		  }, 0);
		  directionsManager.addWaypoint(home);

		  //TO
		  var apt = new Microsoft.Maps.Directions.Waypoint({
			address: to_bing_data_obj.TargetAddress,
		  }, 1);
		  directionsManager.addWaypoint(apt);

		  //Specify the element in which the itinerary will be rendered.
		  directionsManager.setRenderOptions({
			itineraryContainer: '#directions'
		  });

		  //Calculate directions.
		  Microsoft.Maps.Events.addHandler(directionsManager, 'directionsUpdated', directionsParser);
		  Microsoft.Maps.Events.addHandler(directionsManager, 'directionsError', directionsError);
	  
		  directionsManager.calculateDirections();

		  // Make directions div visible
		  $('#directions').removeAttr("style");
	  }		
	}
	
	function ShowBINGErrors(bing_data_obj, idx)
	{
		window.parent.Xrm.Page.ui.clearFormNotification(idx);
		window.parent.Xrm.Page.ui.setFormNotification(bing_data_obj.errors, "ERROR", idx);
	}
	
  function calcDirectionsByAddress(use_dest_geo_codes) {
	global_use_dest_geo_codes = use_dest_geo_codes;
    loadHomeAndDestAddresses();
	
	map.entities.clear();
	map.layers.clear();
  
    // Calculate Directions
    Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function() {
      //Create an instance of the directions manager.
      directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);

	  directionsManager.clearAll();

	  var from_addr_bingObj = { TargetAddress: '', AddressValidationCompleted: false, valid_address: false, errors: '' };	
	  var to_addr_bingObj = { TargetAddress: '', AddressValidationCompleted: false, valid_address: false, errors: '' };	
	  
	  timer = window.setInterval(function() {
		 //Wait in this timer until we have got results about address validation

		 if (from_addr_bingObj.AddressValidationCompleted) {
			ShowBINGErrors(from_addr_bingObj, '1');
		 }
		 
		 if (to_addr_bingObj.AddressValidationCompleted) {
			ShowBINGErrors(to_addr_bingObj, '2');
		 }
		 
		 if ((from_addr_bingObj.AddressValidationCompleted) && (to_addr_bingObj.AddressValidationCompleted)) {
			GetDirectionsFromBING(from_addr_bingObj, to_addr_bingObj);
		 }
		}, 10);

      // FROM Address
      var adr = window.parent.Xrm.Page.getAttribute("btsss_beneficiaryaddress").getValue();
	  
	  from_addr_bingObj.TargetAddress = adr;
	  ValidateAddressAgainstBING(from_addr_bingObj);

	  // TO Address
	  var dest = "";
	  if (use_dest_geo_codes)
	  {
		dest = window.parent.Xrm.Page.getAttribute("btsss_facilitylatitude").getValue() + "," + window.parent.Xrm.Page.getAttribute("btsss_facilitylongitute").getValue();
	  }
	  else
	  {
		dest = window.parent.Xrm.Page.getAttribute("btsss_facilityaddress").getValue();
	  }
	  
	  to_addr_bingObj.TargetAddress = dest;
	  ValidateAddressAgainstBING(to_addr_bingObj);
    });
  }

  
  // Taken from MSDN
  // This is what you would use to pull distance and time information programatically
  function directionsParser(e) {
    directions = e;
    mileage(e);
  }


	function mileage(e) {
		var roundTrip;
		var totalCost;
		var cost = .51;
		
		//get route index
		var routeIndex = directionsManager.getRequestOptions().routeIndex;

		//get the distance and round to 2 decimal places
		var distance = Math.round(e.routeSummary[routeIndex].distance * 100) / 100;
		
		//populate mileage and cost fields
		var trip = window.parent.Xrm.Page.getAttribute("btsss_typemileage").getValue();
		if (trip == "421750001") {
			roundTrip = distance * 2;
			window.parent.Xrm.Page.getAttribute("btsss_mileagerequested").setValue(roundTrip);
			totalCost = roundTrip * cost;
			totalCost = Math.round(totalCost * 100) / 100;
			window.parent.Xrm.Page.getAttribute("btsss_costrequestedmileage").setValue(totalCost);
		}
		else {
			roundTrip = distance;
			window.parent.Xrm.Page.getAttribute("btsss_mileagerequested").setValue(roundTrip);
			totalCost = roundTrip * cost;
			totalCost = Math.round(totalCost * 100) / 100;
			window.parent.Xrm.Page.getAttribute("btsss_costrequestedmileage").setValue(totalCost);
		}
		
		$("#from_addr_cb_non_geo_code").prop("checked", true);
		if (global_use_dest_geo_codes)
		{
			$("#to_addr_cb_geo_code").prop("checked", true);
		}
		else
		{
			$("#to_addr_cb_non_geo_code").prop("checked", true);
		}
		
	}  
		
  function directionsError(e) {
    alert('Error: ' + e.message + '\r\nResponse Code: ' + e.responseCode)
  }
</script>

<meta><meta></head>
  <body style="word-wrap: break-word;">
	<div>
		<input type="hidden" value="" id="to_addr_cb_non_geo_code">
		<input type="hidden" value="" id="to_addr_cb_geo_code">
		<input type="hidden" value="" id="from_addr_cb_non_geo_code">
		<button type="button" onclick="calcDirectionsByAddress(false)" style="visibility:hidden;" id="bn_calcdir">
			Calculate mileage from address
		</button>
		<button type="button" onclick="calcDirectionsByAddress(true)" style="visibility:hidden;" id="bn_geo_calcdir">
			Calculate mileage from geo codes
		</button>
	</div>
    <div class="col-sm-6 container" id="directionsContainer">
		<div class="row">
			<div id="bingMap" style="height:500px; width:100%;">&nbsp;</div>
		</div>

		<div class="row">
			<div class="pre-scrollable" id="directions" style="display:none">&nbsp;</div>
		</div>
	</div>	
  
</body></html>