/* Common routines across Dimensions */

var drawnAnnotations = new Array();

function initialize() {
  if (document.location.hash) {
    postcode = document.location.hash;
    postcode = postcode.replace(/\#/g, '');
    postcode = postcode.replace(/_/g, ' ');
    $(document).ready(function() {
      $("#prompt_postcode").text(postcode);
      if($.cookie("default_location")) {
        $("input.map_postcode_text").val($.cookie("default_location"));
      } else {
       $("input.map_postcode_text").val(postcode);
      }
    });
  }
  
  handlePostcode(postcode, false);
  // usePointFromPostcode(postcode);
  var defaultcentre = new google.maps.LatLng(51.5, -0.1); // default: central London

  bindZoom();

  var navOptions = {
    position: google.maps.ControlPosition.RIGHT,
    style: google.maps.NavigationControlStyle.SMALL
  };

  var myOptions = {
    zoom: zoom,
    center: defaultcentre,
    mapTypeId: google.maps.MapTypeId.HYBRID,
    mapTypeControl: false,
    navigationControl: false,
    scrollwheel: false
  };

  map = new google.maps.Map(document.getElementById("map_canvas"),
      myOptions);
}

function handlePostcodeForm() {
  handlePostcode(window.document.forms[0].elements['postcode'].value, true);
}

function handlePostcode(postcode, change_url) {
  // is it a postcode?
  text = trimText(postcode);

  if (change_url || text != postcode) {
    window.document.forms[0].elements['postcode'].value = text;
  }

  usePointFromPostcode(text);
  postcode_url = text.replace(' ', '_');

  if (change_url) {
    // update walking directions link, excluding the hashpart
    $.cookie("default_location", text, { expires: 999, path: "/" })
    current_url = window.location.protocol+"//"+window.location.hostname+window.location.pathname;
    current_url = current_url.replace(/\/$/, '');
    current_url += '/walk/'+postcode_url;
  
    $('a#walk_href').attr('href', current_url);
    $('span#prompt_postcode').text(text);
  
    var hash = text.replace(/ /g, '_');
    document.location.hash = hash;
  }

  return false;
}

function trimText(text) {
  var size = text.length;

  while (text.slice(0,1) == " ") {
    text = text.substr(1,size-1);
  }
  while(text.slice(size-1,size)== " ") {
    text = text.substr(0,size-1);
  }
  
  return text;
}

function checkPostcode(text) { // check postcode format is valid
  var size = text.length;

  if (size < 6 || size > 8){ //Code length rule
    return false;
  }
  if (!(isNaN(text.charAt(0)))){ //leftmost character must be alpha character rule
    return false;
  }
  if (isNaN(text.charAt(size-3))){ //first character of inward code must be numeric rule
    return false;
  }
  if (!(isNaN(text.charAt(size-2)))){ //second character of inward code must be alpha rule
    return false;
  }
  if (!(isNaN(text.charAt(size-1)))){ //third character of inward code must be alpha rule
    return false;
  }
  if (!(text.charAt(size-4) == " ")){//space in position length-3 rule
    return false;
   }
  count1 = text.indexOf(" ");count2 = text.lastIndexOf(" ");
  if (count1 != count2){//only one space rule
    return false;
  }
  
  return text.toUpperCase();
}

function bindZoom() {
  $('#zoom_in').click(function() {
    $('#zoom_in').attr('src', "/static/images/zoom_in_button_pressed.png");
    map.setZoom(map.getZoom()+1);
    window.setTimeout(function() { $('#zoom_in').attr('src', "/static/images/zoom_in_button_rest.png"); }, 400);
  });

  $('#zoom_out').click(function() {
    $('#zoom_out').attr('src', "/static/images/zoom_out_button_pressed.png");
    map.setZoom(map.getZoom()-1);
    window.setTimeout(function() { $('#zoom_out').attr('src', "/static/images/zoom_out_button_rest.png"); }, 400);
  });

}

/* postcode search */

function usePointFromPostcode(postcode) {
  localSearch.setSearchCompleteCallback(null, 
    function() {
      if (localSearch.results[0])
      {		
        var resultLat = localSearch.results[0].lat;
        var resultLng = localSearch.results[0].lng;
        var point = new google.maps.LatLng(resultLat,resultLng);

        setCenterToPoint(point);
        draw(point);

        return point;
      }else{
        alert("Postcode not found!");
      }
    });
    
  var checkedPostcode = checkPostcode(postcode);

  if (checkedPostcode) {    
    localSearch.execute(checkedPostcode + ", UK");
  } else {
    localSearch.execute(postcode);
  }

}

/* centering */
function setCenterToPoint(point) {
  map.setCenter(point);
}

/* annotation showing */
function showAnnotations(thePoints) {
	MyOverlay.prototype = new google.maps.OverlayView();
	MyOverlay.prototype.onAdd = function() { }
	MyOverlay.prototype.onRemove = function() { }
	MyOverlay.prototype.draw = function() { }
	function MyOverlay(map) { this.setMap(map); }
	var overlay = new MyOverlay(map);
	var projection = overlay.getProjection();
	
  var annotationPoints = new Array();

  if (drawnAnnotations) {
    for (index in drawnAnnotations) {
      drawnAnnotation = drawnAnnotations[index];
      drawnAnnotation.setMap(null);
      drawnAnnotation = null;
    }
  }


  var image = new google.maps.MarkerImage('/static/images/map_annotation.png',
      new google.maps.Size(58, 58),
      new google.maps.Point(0,0),
      new google.maps.Point(29, 48)
  );

  for (var ai in annotations) {
    distance = annotations[ai][2];

    lineDistance = 0;
    for (i=1; i<thePoints.length; i++) {
      // get distance...
      db = getDistanceBearingLatlngs(thePoints[i-1], thePoints[i], scale_factor);
      newLineDistance = lineDistance+db[0];

      // see if annotation is on this line segment
      if (lineDistance < distance && distance <= newLineDistance) {
        // and if so, get its latlng
        segmentDistance = distance-lineDistance;
        annotationLatLng = getNewDestPoint(thePoints[i-1], segmentDistance, db[1]);

        // place annotation
        var drawnAnnotation = new google.maps.Marker({
          position: annotationLatLng,
          title: annotations[ai][0],
          description: annotations[ai][1],
          map: map,
          icon: image
        });
        
        annotationPoints.push(annotationLatLng);
        drawnAnnotations.push(drawnAnnotation);

		google.maps.event.addListener(drawnAnnotation, 'click', function(mouseevent) {
			var infowindow = new google.maps.InfoWindow({
				content: '<div class="infowindow"><p class="title">' + this.title + '</p><p class="description">' + this.description + '</p>',
				maxWidth: 180
			});
			infowindow.open(map, this);
		});
		
        break;
      }
      
      // if not, swap line distance
      lineDistance = newLineDistance;
      
    }
  }

  return annotationPoints;
}

/* distance calculation routines */

function getDistanceBearingLatlngs(point1, point2, scale_factor) {
  var distance = getDistanceFrom(point1, point2);
  var bearing = getBearingFrom(point1, point2);
  
  return new Array(distance, bearing);
}

function getDistanceBearingPixels(point1, point2, scale_factor) {
  var dx = point2[0]-point1[0];
  var dy = point2[1]-point1[1];
  var d = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2))*scale_factor;
  // To be honest, I'm not sure why this works, but it does
  var b = Math.atan2(dy, dx)+(Math.PI/2);

  return new Array(d, b);
}

function getNewDestPoint(point1, d, brng) {
  var deg = brng.toDeg()
  if (deg < 0) {
    deg += 360;
  }

  var lat1 = point1.lat().toRad(); var lon1 = point1.lng().toRad();

  var R = 6378.137; // km, matches Google's version

  var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) + 
                        Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) );
  var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1), 
                               Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));

  var destpoint = new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
  
  return destpoint;
}

// functions for remapping existing latlongs
function getDistanceFrom(point1, point2) {
  var lat1 = point1.lat(); var lon1 = point1.lng();
  var lat2 = point2.lat(); var lon2 = point2.lng();

  var R = 6378.137; // km, matches Google's version

  var dLat = (lat2-lat1).toRad();
  var dLon = (lon2-lon1).toRad(); 
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
          Math.sin(dLon/2) * Math.sin(dLon/2); 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c;
  return d;
} 

function getBearingFrom(point1, point2) {
  var lat1 = point1.lat(); var lon1 = point1.lng();
  var lat2 = point2.lat(); var lon2 = point2.lng();

  var R = 6378.137; // km, matches Google's version

  var dLat = (lat2-lat1).toRad();
  var dLon = (lon2-lon1).toRad(); 

  var y = Math.sin(dLon) * Math.cos(lat2.toRad());
  var x = Math.cos(lat1.toRad())*Math.sin(lat2.toRad()) -
          Math.sin(lat1.toRad())*Math.cos(lat2.toRad())*Math.cos(dLon);
  var brng = Math.atan2(y, x);

  // if (brng < 0) {
  //     brng += 2 * Math.PI;
  //}
  return brng;
}

if (typeof(String.prototype.toRad) === "undefined") {
  Number.prototype.toRad = function() {
    return this * Math.PI / 180;
  }
}

/** Convert radians to numeric (signed) degrees */
if (typeof(String.prototype.toDeg) === "undefined") {
  Number.prototype.toDeg = function() {
    return this * 180 / Math.PI;
  }
}

