/*
 * Utils
 */
function distanceFormat(meters) {
	var metersPerUnit = typeof(glbMetersPerUnit) != 'undefined' ? glbMetersPerUnit : 1000;
  return (meters/metersPerUnit).toFixed(2);
}
/*
 * Setup the flash notice fade
 */
$(document).ready(
  function() {
    if ($('#flash_notice') != null) {
      setTimeout("$('#flash_notice').fadeOut('slow').slideUp('slow')", 5000);
    }
	}
);

/*
 * Setup the calendar
 */
$(document).ready(
  function() {
		InitCalendar();
	} 
);
function InitCalendar(){
	$('#calendar td a').click(function(e){
		$(this).blur();
		$('#log_exercise_date, #goal_date').focus();
		var ep = $(this).attr('title');
		$('#log_exercise_date, #goal_date').val(ep);
		$('#calendar td a').removeClass('chosen_date');
		$(this).addClass('chosen_date');
		
		return false;
	});
	
	$('#calendar th a').click(
    function(e){
			$('#log_exercise_date, #goal_date').focus();
    }
	);
	
	$('#earlier a').click(function(){
		var start = $(this).attr('href');
		$('#date_picker_wrapper').load('/default/dateSelectCalendar', { prev: 1, start: start });
		return false;
	});
	$('#later a').click(function(){
		var start = $(this).attr('href');
		$('#date_picker_wrapper').load('/default/dateSelectCalendar', { next: 1, start: start });
		return false;
	});

}

/*
 * Setup statistics page 
 */

$(document).ready(
  function() {
		var hoverTimeout = null;
		$('.statisticsListing td.title a').hover(
		  function() {
				$(this).parent().prev().find('a').show();
			},
			function() {
				var elm = this;
				var icon = $(elm).parent().prev().find("a");
				hoverTimeout = setTimeout(function() {icon.hide()},500);
				
			}
		);
		
	 $('.statisticsListing td.delete a').click(
      function() {
        if (confirm('Sure you want to delete this?')) {
					clearTimeout(hoverTimeout);
					return true;
				} else {
					return false;
				}
      }
    );
		$('.statisticsListing td.delete a').hover(
		  function(){
				clearTimeout(hoverTimeout);
	    },
			function() {
				icon = $(this);
				hoverTimeout = setTimeout(function() {icon.hide()},500);
			}
		);
	}
	
);

/*
 * Set up log form inputs
 */
$(document).ready(
  function() {
    $('input[type=text], input[type=password]' ).focus(
		  function() {
				$(this).addClass('has_focus');
				if ($(this).attr('id') == 'log_exercise_date' || $(this).attr('id') == 'goal_date') {
					$('#calendar').addClass('has_focus');
				}
				
				// Tool tips
				$(this).siblings('.input_tip').html(
          $(this).siblings('.hidden_input_tip').html()
        );
			}
		);
		$('input').blur(
      function() {
        $(this).removeClass('has_focus');
				if ($(this).attr('id') == 'log_exercise_date') {
          $('#calendar').removeClass('has_focus');
        }
				
				$(this).siblings('.input_tip').html('');
      }
    );
		/*
		 * Past route loading
		 */
		$('#past_routes a').click(
		  function() {
				var id = $(this).attr('href').replace(/.*?route_id=(\d+)$/,"$1");
				if (UpdateMapWithRoute(id)) {
			   return false;
		    } else {
					return true;
				}
			}
	  );
				
	}
);

/*
 * Set up the Google Map
 */

var gmapLoaded = false;
$(document).ready(
  function() {
		
		$('a.mapPointer').hover(
		function() {
		  $('#map_cntrl .mapPointer').show();	
		},
		function() {
      $('#map_cntrl .mapPointer').hide(); 
    }
		);
		$('#map_cntrl').click(
		  function(e){
				$('#map_dialog').toggle();
				if (!gmapLoaded) {
			     loadGMap();
					 gmapLoaded = true;
		    }
				
	  	  return false;
      }
		);
		
		$('.map_cntrl').click(
		  function() {
				$('#map_dialog').show();
				if (!gmapLoaded) {
           loadGMap();
           gmapLoaded = true;
        } else {
					mapRoute.setReadOnly(false);
				}
				
				var id = $(this).attr('href').replace(/.*#(\d+)$/,"$1");
        $.getJSON('/route/' + id,
			    function(route) {
						mapRoute.clearRoute();
			      for (var i = 0;i<route.waypoints.length; i++) {
			        var point = route.waypoints[i];
			        if (typeof(point) == 'undefined') continue;
			        mapRoute.addPoint(null, new GLatLng(point[0], point[1]));
			      }
						mapRoute.setReadOnly(true);
			    }
        );
				
				
				return false;
			}
		);
		
		if ($('#map_dialog.display_map').length > 0) {

			if (!gmapLoaded) {
				$('#map_dialog').toggle();
        loadGMap();
        
      }
    }
  }
);

function ResetMapRoute(){
  if (gmapLoaded) {
    mapRoute.clearRoute();
    $('input[name^=waypoints]').each(function(i, elm){
    var ll = $(elm).val().split(',');
    mapRoute.addPoint(null, new GLatLng(ll[0], ll[1]))
    });
  }
}

function UpdateMapWithRoute(id) {
  $.getJSON('/route/' + id,
    function(route) {
      $('#log_route_id').val(id);
      $('#log_distance').val(distanceFormat(route.distance));
      $('input[name^=waypoints]').remove();
        
      for (var i = 0;i<route.waypoints.length; i++) {
        var point = route.waypoints[i];
        if (typeof(point) == 'undefined') continue;
        var hiddenInput = $(document.createElement('input'));
        
        $(hiddenInput).attr('type','hidden');
        $(hiddenInput).attr('name','waypoints[]');
        
        $(hiddenInput).attr('value',point[0] + "," + point[1]);          
        $('#log_add_form').append(hiddenInput);
      }
      ResetMapRoute();
    }
	);
	
	return true;
}
		
function loadGMap() {
  if (GBrowserIsCompatible()) {
		$('#map').width('100%');
		$('#map').height('90%');
		
    var map = new GMap2(document.getElementById("map"), { "draggableCursor": "crosshair" });
		
    map.setCenter(new GLatLng(glbDefaultCenter[0],glbDefaultCenter[1]), 13);
		map.addControl(new GSmallMapControl());
		map.addControl(new GScaleControl());
	  mapRoute = new MapRoute(map);
		
		gmapLoaded = true;
		
		$('#undo').click(
		  function() {
				mapRoute.removeLastPoint();
				return false;
			}
		);
		
		$('#return_home').click(
      function() {
        mapRoute.returnHome();
        return false;
      }
    );
		
		$('#starting_from').submit(
		  function() {
				var address = $('#address').val();
			  mapRoute.centerMapOnAddress(address);			
        return false;
			}
		);
		$('#address').focus(
		  function() {
				if ($(this).val() == 'your starting address?') {
					$(this).val('')
				}
			}
		);
		$('#address').blur(
      function() {
        if ($(this).val() == '') {
          $(this).val('your starting address?')
        }
      }
    );
		
		mapRoute.addListener('routeupdate', $('#route_distance'));
		var metersPerUnit = typeof(glbMetersPerUnit) != 'undefined' ? glbMetersPerUnit : 1000;
		$('#route_distance').bind('routeupdate',
		  function(e) {
				$(this).text((mapRoute.getDistance()/metersPerUnit).toFixed(2));
			}
		);
		
		
    $('#close_map_dialog').click(
		  function() {
			 	$('#map_dialog').hide();
			}
	  );
		
		$('#done').click(
      function() {
        $('#log_distance').val((mapRoute.getDistance()/metersPerUnit).toFixed(2));
        $('#map_dialog').toggle();
        var route = mapRoute.getRoute();
				var hiddenInputs = new Array();
				$('input[name^=waypoints]').remove();

				for (var i = 0; i < route.length; i++) {
					var latLng = route[i];
					var hiddenInput = document.createElement('INPUT');
					$(hiddenInput).attr('type','hidden');
					$(hiddenInput).attr('name','waypoints[]');
					$(hiddenInput).attr('value',latLng.lat() + "," + latLng.lng());
					
					$('#log_add_form').append(hiddenInput);
				}
				
				return false;
      }
    );
		
		ResetMapRoute();
  }
}

/*
 * Map Application constructed with a Google map object
 */
function MapRoute(map){
	this.map = map;
	this.route = new Array();
	this.routeOverlays = new Array();
	this.distance = 0.0;
	this.readOnly = false;
	this.listeners = {
		routeupdate: new Array()
	}
	
	/**
	 * If the last point is close to the edge of the
	 * map then pan the map in that direction some
	 */
	this.panMapIfNeeded = function() {
		if (this.route.length < 1) return;
		
		var bounds = this.map.getBounds();
		var ne = bounds.getNorthEast();
		var sw = bounds.getSouthWest();
		var incr = 0.2*(ne.lat()-sw.lat()); // this close to edge
		ne = new GLatLng(ne.lat() - incr, ne.lng() - incr, true);
		sw = new GLatLng(sw.lat() + incr, sw.lng() + incr, true);
		var lastPoint = this.route[this.route.length - 1];
		var innerBounds = new GLatLngBounds( sw, ne);
		if (! innerBounds.containsLatLng(lastPoint)) {
			this.map.panTo(lastPoint);
		}
	}
	
	/*
	 * Adds a point to the route and draws the line
	 */
	this.addPoint = function(overlay, glatlng){
		if (this.isReadOnly()) return;
		
		if (glatlng == null) {
			glatlng = overlay.getLatLng();
		}
		var overLay;
		if (this.route.length > 0) {
			// Add a line to the new point
			var prevPoint = this.route[this.route.length - 1];
			overLay = new GPolyline([prevPoint, glatlng], "#e90024", 3);
			var endIconOverLay = new GMarker(glatlng);
		}
		else {
			// Must be the beginning so add a start icon
			overLay = new GMarker(glatlng);
		}
		this.map.addOverlay(overLay);
		this.routeOverlays.push(overLay);
		this.route.push(glatlng);
		
		
		this.panMapIfNeeded();
		this.triggerEvent('routeupdate');
	}
	
	/*
	 * Pops the last point off the stacks
	 * and removes the line from the map
	 */
	this.removeLastPoint = function(){
		if (this.isReadOnly()) return;
		
		this.route.pop();
		this.map.removeOverlay(this.routeOverlays.pop());
		this.panMapIfNeeded();
		this.triggerEvent('routeupdate');
	}
	
	this.clearRoute = function() {
		if (this.isReadOnly()) return;
		
		while (this.route.length > 0) {
			this.removeLastPoint();
		}
	}
	
	/*
	 * Adds points from last back to start
	 * i.e. retraces way points back to start
	 */
	this.returnHome = function(){
		if (this.isReadOnly()) return;
		
		if (this.route.length > 1) {
			for (var i = this.route.length - 2; i >= 0; i--) {
				var backtrackPoint = this.route[i];
				var wayPoint = new GLatLng(backtrackPoint.lat(), backtrackPoint.lng());
				this.addPoint(null, wayPoint);
				
			}
		}
	}
	
	/**
	 * Returns array of the routes lat/longs
	 */
	this.getRoute = function() {
		return this.route;
	}
	
	/*
	 * Updates the distance based on the waypoints so far
	 */
	this.updateDistance = function(){
		this.distance = 0;
		for (var i = 1; i < this.route.length; i++) {
			ptOne = this.route[i - 1];
			ptTwo = this.route[i];
			this.distance += ptOne.distanceFrom(ptTwo);
		}
	}
	
	/**
	 * Returns the distance calculated from the waypoints
	 */
	this.getDistance = function(){
		this.updateDistance();
		return this.distance;
	}
	
	/**
	 * Center the map on the given address
	 */
	this.centerMapOnAddress = function(address){
	  var thisMap = this.map;
		var geocoder = new GClientGeocoder();
		geocoder.getLatLng(address, function(point){
			if (!point) {
				alert(address + " not found");
			}
			else {
				thisMap.setCenter(point, 13);
			}
		});
	}
  
	/*
	 * Add a a listener of certain type events.
	 * 
	 * type routeupdate
	 */
	this.addListener = function(type, elm) {
		this.listeners[type].push(elm);
	}
	
	this.triggerEvent = function(type) {
		for (var i = 0; i < this.listeners[type].length;i++) {
			$(this.listeners[type][i]).trigger(type);
		}
	}
	
	this.setReadOnly = function(v) {
		this.readOnly = v;
	}
	
	this.isReadOnly = function() {
		return this.readOnly;
	}
	
	/**
	 * Binds the addPoint method with the Gmaps click event
	 */
	GEvent.bind(this.map, "click", this, 
	 this.addPoint
	);
	
}


