// index.js
/*
Copyright 2008 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
 * @fileoverview This is the main JavaScript file for the Driving Simulator
 * @author Roman Nurik
 * @supported Tested in IE6+ and FF2+
 */

/**
 * The global Directions object for the currently loaded directions
 * @type {google.maps.Directions}
 */
//var DS_directions = null;

/**
 * The list of driving steps loaded from google.maps.Directions
 * @type {Array.<Object>}
 */
var DS_steps = [];

/**
 * The list of path vertices and their metadata for the driving directions
 * @type {Array.<Object>}
 */
var DS_path = []; // entire driving path

/**
 * The global simulator instance that conducts the driving simulation
 * @type {DDSimulator}
 */
var DS_simulator; // instance of the DDSimulator class

/**
 * The car marker that appears on the reference map to the right of the main
 * simulation screen
 * @type {google.maps.Marker}
 */
//var DS_mapMarker = null; // car marker on the Map

/**
 * Instead of using the plugin's built-in ID system, which doesn't like when
 * IDs are reused, we will use a separate dictionary mapping ID to placemark
 * object
 * @type {Object}
 */
var DS_placemarks = {};

var points = new Array();

function DS_loadRoute()
{
	points.length= 0;
	if(route_data != '')
	{
		var lineStringPlacemark = DS_ge.createPlacemark('');
		if (!lineStringPlacemark.getStyleSelector()) {
			lineStringPlacemark.setStyleSelector(DS_ge.createStyle(''));
		}
		var lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
		lineStyle.setWidth(5);
		lineStyle.getColor().set('ff000080');
		var lineString = DS_ge.createLineString('');
		lineString.setTessellate(true);

		var coords = lineString.getCoordinates();
		var pointStrings = route_data.split(',');
		for(var i=0 ; i<pointStrings.length; i++)
		{
			var point = pointStrings[i].split(':');
			var lat = parseFloat(point[0]);
			var lng = parseFloat(point[1]);
			points[i] = new GLatLng(lat, lng);
			
			coords.pushLatLngAlt(lat, lng, 0 );
			if(i==0){
				startLat = lat;
				startLng = lng;
			}
		}
		lineStringPlacemark.setGeometry(lineString);
		DS_ge.getFeatures().appendChild(lineStringPlacemark);

		// fly to the start of the route
		DS_flyToLatLng(new google.maps.LatLng(startLat, startLng));

		// enable the simulator controls
		$('#simulator-form input').removeAttr('disabled');

		// destroy the simulator if exists
		if (DS_simulator) {
			DS_simulator.destroy();
			DS_simulator = null;
		}
		DS_buildPathStepArrays();
	}
}


/**
 * Generates the DS_path and DS_step arrays from the global DS_directions
 * instance
 * 
 * NOTE: only the first route is used
 */
function DS_buildPathStepArrays() {
	// begin processing the directions' steps and path
	DS_steps = [];
	DS_path = [];

	//  var polyline = DS_directions.getPolyline();
	//  var route = DS_directions.getRoute(0);
	var numPolylineVertices = points.length;
  
	DS_steps.push({
		loc: points[0],
		desc: 'Start',
		distanceHtml: '',
		pathIndex: 0
	});
    
    for (var j = 0; j <= numPolylineVertices-1; j++) {
      var loc = points[j];
      var distance = (j == numPolylineVertices - 1) ?
                     0 : DS_geHelpers.distance(loc, points[j + 1]);
      
      DS_path.push({
        loc: loc,
        step: 1,
        distance: distance,
        
        // this segment's time duration is proportional to its length in
        // relation to the length of the step
        duration:  distance * 0.745666
      });
      
    }
}


/**
 * Fly the camera to the given step index in the route, and highlight it in
 * the directions list. Also show the placemark description balloon.
 * @param {number} stepNum The 0-based step index to fly to
 */
function DS_flyToStep(stepNum) {
  var step = DS_steps[stepNum];
  
  var la = DS_ge.createLookAt('');
  la.set(step.loc.lat(), step.loc.lng(),
      0, // altitude
      DS_ge.ALTITUDE_RELATIVE_TO_GROUND,
      DS_geHelpers.getHeading(step.loc, DS_path[step.pathIndex + 1].loc),
      75, // tilt
      40 // range (inverse of zoom)
      );
  DS_ge.getView().setAbstractView(la);

  // show the description balloon.
  var balloon = DS_ge.createFeatureBalloon('');
  balloon.setFeature(DS_placemarks['step-' + stepNum]);
  DS_ge.setBalloon(balloon); 

  DS_highlightStep(stepNum);
}

/**
 * Highlights the given step in the left directions list
 * @param {number} stepNum The 0-based step index to highlight in the
 *     directions list
function DS_highlightStep(stepNum) {
  $('#route-details li').removeClass('sel');
  $('#route-details #dir-step-' + stepNum).addClass('sel');
}
 */

/**
 * Move the camera to the given location, staring straight down, and unhighlight
 * all items in the left directions list
 * @param {google.maps.LatLng} loc The location to fly the camera to
 */
function DS_flyToLatLng(loc) {
  var la = DS_ge.createLookAt('');
  la.set(loc.lat(), loc.lng(),
      10, // altitude
      DS_ge.ALTITUDE_RELATIVE_TO_GROUND,
      90, // heading
      0, // tilt
      200 // range (inverse of zoom)
      );
  DS_ge.getView().setAbstractView(la);
  
  $('#route-details li').removeClass('sel');
}

/**
 * Formats a time given in seconds to a human readable format
 * @param {number} s Time in seconds
 * @return {string} A string formatted in hh:mm form representing the given
 *     number of seconds
 */
function DS_formatTime(s) {
  var m = Math.floor(s / 60);
  s %= 60;
  var h = Math.floor(m / 60);
  m %= 60;
  s = Math.round(s);
  return h + ' hours ' + ((m < 10) ? ('0' + m) : m)+ ' mins';
}

/**
 * Simulator controls
 * @param {string} command The control command to run
 * @param {Function?} opt_cb Optional callback to run when the command
 *     completes its task
 */
function DS_controlSimulator(command, opt_cb) {
  switch (command) {
    case 'reset':
      if (DS_simulator)
        DS_simulator.destroy();
      
      // create a DDSimulator object for the current DS_path array
      // on the DS_ge Earth instance
      DS_simulator = new DDSimulator(DS_ge, DS_path, {
        // as the simulator runs, reposition the map on the right and the
        // car marker on the map, and update the status box on the bottom
        on_tick: function() {
      
          if (DS_simulator) {
            $('#status').html(
                '<strong>Time:</strong> ' +
                  DS_formatTime(DS_simulator.totalTime) + '<br/>' +
                '<strong>Distance:</strong> ' +
                  (Math.round(
                      DS_simulator.totalDistance / 1609.344 * 10) / 10) +
                  ' miles' + '<br/>' +
                '<strong>Current Speed:</strong> ' +
                  Math.round(DS_simulator.currentSpeed / 0.044704)/10 + 'mph') +
                  '<br/>';
          }
        },
        
        // when the simulator moves to a new step (specified as an integer
        // index in DS_path items), highlight that step in the directions
        // list
        on_changeStep: function(stepNum) {
//          DS_highlightStep(stepNum);
        }
      });
      
      DS_updateSpeedIndicator();
      DS_simulator.initUI(opt_cb);
      break;
    
    case 'start':
      if (!DS_simulator)
        DS_controlSimulator('reset', function() {
          DS_simulator.start();
          if (opt_cb) opt_cb();
        });
      else {
        DS_simulator.start();
        if (opt_cb) opt_cb();
      }
      break;
    
    case 'pause':
      if (DS_simulator)
        DS_simulator.stop();
      
      if (opt_cb) opt_cb();
      break;
    
    case 'resume':
      if (DS_simulator)
        DS_simulator.start();
      
      if (opt_cb) opt_cb();
      break;
    
    case 'slower':
      if (DS_simulator && DS_simulator.options.speed > 1) {
        DS_simulator.options.speed /= 2.0;
        DS_updateSpeedIndicator();
      }
      break;
    
    case 'faster':
      if (DS_simulator && DS_simulator.options.speed < 128.0) {
        DS_simulator.options.speed *= 2.0;
        DS_updateSpeedIndicator();
      }
      break;
  }
}

/**
 * Update the speed indicator in the simulation controls box to reflect
 * the current simulation speed multiplier
 */
function DS_updateSpeedIndicator() {
    $('#speed-indicator').text(Math.floor(DS_simulator.options.speed) + 'x');
}

