var landscape = false;

var settingsCookie = null;
var lastCookie = null;
var targetCookie = null;
var targetsCookie = null;
var locationTimer = null;

var position = {
    lat: 0
    ,lng: 0
    ,alt: 0
  }

var target = null;
/*
var target = {
    name: "Test"
    ,lat: 12
    ,lng: 34
    ,alt: 100
}
*/

var settings = {
  isMetric: true
}

var lastId = 0;
var targets = [];
var phone = testPhone;
var bearing = null;
var compassBearing = 0;
var currentBearing = 0;
var roseImg;
var roseImg2;
var compassHidden = false;

function setup() {
  Cookie_wait(function() {
    orientationChanged();
    /*
    if (navigator.userAgent.toLowerCase().indexOf("iphone") >= 0) {
      phone = iPhone;
    }  
    */
    if (navigator.userAgent.toLowerCase().indexOf("android") >= 0) {
      phone = gPhone;
    }
    phone.setup();
    if (navigator.language.toLowerCase().indexOf("en") >= 0) {
      settings.isMetric = false;
    }  
    settingsCookie = createCookie("MyPosition-Settings");
    if (settingsCookie.get()) {
      try {
        settings = eval("new Object({" + settingsCookie.get() + "})");
      }
      catch (e) {
        alert(e);
      }  
    }
    lastCookie = createCookie("MyPosition-Last");
    if (lastCookie.get()) {
      try {
        position = eval("new Object({" + lastCookie.get() + "})");
      }
      catch (e) {
        alert(e);
      }  
    }  
    targetCookie = createCookie("MyPosition-Target");
    if (targetCookie.get()) {
      try {
        target = eval("new Object({" + targetCookie.get() + "})");
        fillNewTarget(target);
      }
      catch (e) {
        alert(e);
      }  
    }
    loadTargets();
    if (targets.length == 0) {
      createDefaultTargets();
    }
    roseImg = new Image();
    roseImg.src = 'rose50.png';
    roseImg.onload = function() {
      roseImg.loaded = true;
      redrawCompass();
    }  
    roseImg2 = new Image();
    roseImg2.src = 'rose260.png';
    roseImg2.onload = function() {
      roseImg2.loaded = true;
      redrawCompass();
    }  
    $("Loading").style.display = "none";
    setPosition();
    //updatePosition();
  });
}

function createDefaultTargets() {
  var newTarget = {
      id: ++lastId
      ,name: "North pole"
      ,lat: 90
      ,lng: 0
      ,alt: 0
    }
  addTargetToList(newTarget);
  newTarget = {
      id: ++lastId
      ,name: "South pole"
      ,lat: -90
      ,lng: 0
      ,alt: 2835
    }
  addTargetToList(newTarget);
  newTarget = {
      id: ++lastId
      ,name: "New York"
      ,lat: 40.71427
      ,lng: -74.00597
      ,alt: 10
    }
  addTargetToList(newTarget);
  newTarget = {
      id: ++lastId
      ,name: "San Francisco"
      ,lat: 37.77493
      ,lng: -122.41942
      ,alt: 16
    }
  addTargetToList(newTarget);
}

function setBearing(newBearing) {
  compassBearing = parseInt(newBearing);//parseInt(newBearing * 180 / Math.PI + 360) % 360;
  $("CompassValue").innerHTML = compassBearing + "&deg;";
  currentBearing = compassBearing;
  redrawCompass();
}

function redrawCompass() {
  if (compassHidden) {
    return;
  }  
  drawCanvas($("SmallCompass"), roseImg);
  drawCanvas($("BigCompass"), roseImg2);
}

function drawCanvas(canvas, img) {
  if (!img.loaded) {
    return;
  }  
  var ctx = canvas.getContext("2d");
  var width = canvas.width;
  var height = canvas.height;
  ctx.clearRect(0, 0, width, height);
  ctx.save();
  ctx.translate(width / 2, height / 2);
  ctx.rotate(-currentBearing * Math.PI / 180);
  ctx.drawImage(img, -width / 2, -height / 2);

  if (bearing != null) {
    var radius = canvas.width / 2;
    var sunAngle = -bearing * Math.PI / 180;
    ctx.beginPath();
    ctx.globalAlpha = 0.5;
    ctx.strokeStyle = "rgb(0, 0, 0)";
    ctx.lineWidth = 4;
    ctx.lineCap = "round";
    ctx.moveTo(0, 0);
    ctx.lineTo(-radius * Math.sin(sunAngle), -radius * Math.cos(sunAngle));
    ctx.stroke();
    ctx.globalAlpha = 0.8;
    ctx.strokeStyle = "rgb(255, 0, 0)";
    ctx.lineWidth = 2;
    ctx.lineCap = "round";
    ctx.moveTo(0, 0);
    ctx.lineTo(-radius * Math.sin(sunAngle), -radius * Math.cos(sunAngle));
    ctx.stroke();
    ctx.closePath();
  }
  
  ctx.restore();
}

function updatePosition() {
  phone.updateLocation(function(lat, lng) {
  });  
}
                       
function startLocation() {
  $("LoadingText").innerHTML = "Updating...";
  $("Loading").style.display = "block";
  if (locationTimer) {
    clearTimeout(locationTimer);
  }  
  locationTimer = setTimeout(function() {
    setLocation('error');  
  }, 60000);
}

function setLocation(lat, lng, alt, accuracy, speed, satellites) {
  if (locationTimer) {
    clearTimeout(locationTimer);
    locationTimer = null;
  }
  $("Loading").style.display = "none";
  if (lat == 'error') {
    $("TimeStamp").innerHTML = "Update failed";
    return;
  }  
  position.lat = lat;
  position.lng = lng;
  position.alt = alt;
  position.accuracy = accuracy;
  position.speed = speed;
  position.satellites = satellites;
  position.timeStamp = new Date().getTime();
  setPosition();
  savePosition();
}
  
function setPosition() {
  if (!target) {
    $("TargetData").style.display = "none";
    $("TargetName").innerHTML = "<i>No Target</i>";
    bearing = null;
    $("SmallCompass").style.float = "none";
    $("CompassDistance").innerHTML = "";
  }
  else {
    $("TargetData").style.display = "";
    if (target.name.length > 0) {
      $("TargetName").innerHTML = target.name;
    }
    else {
      $("TargetName").innerHTML = "Target";
    }  
    $("SmallCompass").style.float = "";
    $("DistanceValue").innerHTML = prepareDistance(getConstantDistance(position.lat, position.lng, target.lat, target.lng));
    bearing = getConstantBearing(position.lat, position.lng, target.lat, target.lng);
    redrawCompass();
    $("BearingValue").innerHTML = prepareNumber(bearing, -1);
    if (target.alt != null && position.alt != null) {
      $("HeightRow").style.display = "";
      $("HeightValue").innerHTML = prepareHeight(target.alt - position.alt);
    }
    else {
      $("HeightRow").style.display = "none";
    }  
    $("CompassDistance").innerHTML = "<b>Distance:</b>&nbsp;" + $("DistanceValue").innerHTML;
    if (position.accuracy) {
      $("CompassAccuracy").innerHTML = "<br><b>Accuracy:</b>&nbsp;" + position.accuracy + "m";
    }
    else {
      $("CompassAccuracy").innerHTML = "";
    }  
    if (position.speed) {
      $("CompassSpeed").innerHTML = "<br><b>Speed:</b>&nbsp;" + position.speed;
    }
    else {
      $("CompassSpeed").innerHTML = "";
    }  
    if (position.satellites) {
      $("CompassSatellites").innerHTML = "<br><b>Satellites:</b>&nbsp;" + position.satelittes;
    }
    else {
      $("CompassSatellites").innerHTML = "";
    }  
  }  
  $("LatValue").innerHTML = prepareNumber(position.lat);
  $("LngValue").innerHTML = prepareNumber(position.lng);
  if (position.alt == null) {
    $("AltValue").innerHTML = "---";
  }
  else {
    $("AltValue").innerHTML = prepareHeight(position.alt);
  }
  if (position.timeStamp) {
    var date = new Date(position.timeStamp);
    $("TimeStamp").innerHTML = "Last update: " + date.toLocaleString();
  }
  else {
    $("TimeStamp").innerHTML = "";
  }
}

function prepareNumber(number, precision) {
  if (!precision) {
    precision = 6;
  }
  if (precision < 0) {
    return parseInt(number) + "&deg;";
  }  
  return number.toPrecision(precision) + "&deg;";
}

function prepareDistance(number) {
  if (settings.isMetric) {
    if (number < 1) {
      return parseInt(number * 1000) + "&nbsp;m";
    }
    if (number < 100) {
      return number.toPrecision(3) + "&nbsp;km";
    }  
    return parseInt(number) + "&nbsp;km";
  }
  var miles = number / 1.609;
  if (miles < 1) {
    return parseInt(miles * 1760) + "&nbsp;yd";
  }  
  if (miles < 100) {
    return miles.toPrecision(3) + "&nbsp;mi";
  }  
  return parseInt(miles) + "&nbsp;mi";
}

function prepareHeight(number) {
  if (settings.isMetric) {
    return parseInt(number) + "&nbsp;m";
  }
  return parseInt(number * 3.280) + "&nbsp;ft";
}

function toggleMetric() {
  settings.isMetric = !settings.isMetric;
  setPosition();
  fillNewTarget(target);
  saveSettings();
}

function toRad(value) {
  return value * Math.PI / 180;
}

function getDistance(lat1, lon1, lat2, lon2) {
  var R = 6371; // km
  var dLat = toRad(lat2-lat1);
  var dLon = toRad(lon2-lon1); 
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * 
          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 getBearing(lat1, lon1, lat2, lon2) {
  var dLon = toRad(lon2 - lon1);
  lat1 = toRad(lat1);
  lat2 = toRad(lat2);
  var y = Math.sin(dLon) * Math.cos(lat2);
  var x = Math.cos(lat1)*Math.sin(lat2) -
          Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
  var brng = Math.atan2(y, x);
  return (brng * 180 / Math.PI + 360) % 360;
}

function getConstantDistance(lat1, lon1, lat2, lon2) {
  var R = 6371; // km
  var dLat = toRad(lat2 - lat1);
  var dLon = toRad(lon2 -lon1);
  lat1 = toRad(lat1);
  lat2 = toRad(lat2);
  var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));
  var q = (Math.abs(dLat) > 1e-10) ? dLat/dPhi : Math.cos(lat1);
  // if dLon over 180° take shorter rhumb across 180° meridian:
  if (Math.abs(dLon) > Math.PI) {
    dLon = dLon>0 ? -(2*Math.PI-dLon) : (2*Math.PI+dLon);
  }
  var d = Math.sqrt(dLat*dLat + q*q*dLon*dLon) * R;
  return d;
}

function getConstantBearing(lat1, lon1, lat2, lon2) {
  var dLat = toRad(lat2 - lat1);
  var dLon = toRad(lon2 -lon1);
  lat1 = toRad(lat1);
  lat2 = toRad(lat2);
  var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4));
  var q = (Math.abs(dLat) > 1e-10) ? dLat/dPhi : Math.cos(lat1);
  // if dLon over 180° take shorter rhumb across 180° meridian:
  if (Math.abs(dLon) > Math.PI) {
    dLon = dLon>0 ? -(2*Math.PI-dLon) : (2*Math.PI+dLon);
  }
  var brng = Math.atan2(dLon, dPhi);
  return (brng * 180 / Math.PI + 360) % 360
}

function showTargets() {
  compassHidden = true;
  phone.pauseUpdates(true);
  setTimeout(function() { $("Targets").style.opacity = "1"}, 1);
  $("Targets").style.display = "block";
  $("MainSection").style.display = "none";  
  $("MainSection").style.opacity = "0";
  window.scrollTo(0, 0);
}

function setCurrent() {
  fillNewTarget(position);
}

function clearTarget() {
  $("NameNewValue").value = "";
  $("LatNewValue").value = "0";
  $("LngNewValue").value = "0";
  $("AltNewValue").value = "0";
  target = null;
  targetCookie.remove();
  setPosition();
}

function showNewTargetMap() {
  var newTarget = readTarget();
  if (target) {
    phone.showLocation(newTarget.lat, newTarget.lng);
  }  
}

function fillNewTarget(newTarget) {
  if (!newTarget.name) {
    $("NameNewValue").value = "";
  }
  else {
    $("NameNewValue").value = newTarget.name;
  }  
  $("LatNewValue").value = newTarget.lat; 
  $("LngNewValue").value = newTarget.lng;
  if (newTarget.alt) {
    if (settings.isMetric) {
      $("AltNewValue").value = newTarget.alt;
    }
    else {
      $("AltNewValue").value = Math.round(newTarget.alt * 3.28);
    }  
  }
  else {
    $("AltNewValue").value = "";
  }  
}

function readTarget() {
  var newTarget = new Object();
  newTarget.name = $("NameNewValue").value;
  newTarget.lat = parseFloat($("LatNewValue").value);
  if (isNaN(newTarget.lat)) {
    return null;
  }
  newTarget.lng = parseFloat($("LngNewValue").value);
  if (isNaN(newTarget.lng)) {
    return null;
  }
  newTarget.alt = parseInt($("AltNewValue").value);
  if (isNaN(newTarget.alt)) {
    newTarget.alt = null;
  }
  else {
    if (!settings.isMetric) {
      newTarget.alt = Math.round(newTarget.alt / 3.28);
    }  
  }  
  return newTarget;
}  

function setTarget() {  
  var newTarget = readTarget();
  if (!newTarget) {
    return;
  }  
  compassHidden = false;
  target = newTarget;
  saveTarget();
  setPosition();
  showForm();
}

function checkValue(input) {
  var value = parseFloat(input.value);
  if (isNaN(value)) {
    input.style.background = "#FFE0E0";
  }
  else {
    input.style.background = "";
  }  
}

function showForm() {
  compassHidden = false;
  phone.pauseUpdates(false);
  $("Targets").style.opacity = "0";
  $("Targets").style.display = "none";
  $("MainSection").style.display = "block";    
  setTimeout(function() { $("MainSection").style.opacity = "1"}, 1);
  window.scrollTo(0, 0);
}

function showCompass() {  
  $("MainSection").style.opacity = "0";
  $("MainSection").style.display = "none";
  $("CompassSection").style.display = "block";    
  setTimeout(function() { $("CompassSection").style.opacity = "1"}, 1);
  window.scrollTo(0, 0);
}

function closeCompass() {  
  $("CompassSection").style.opacity = "0";
  $("CompassSection").style.display = "none";
  $("MainSection").style.display = "block";    
  setTimeout(function() { $("MainSection").style.opacity = "1"}, 1);
  window.scrollTo(0, 0);
}

function addTarget() {
  var newTarget = readTarget();
  if (!newTarget) {
    return;
  }
  lastId++;
  newTarget.id = lastId;
  addTargetToList(newTarget, true);
}

function addTargetToList(newTarget, first) {
  var noEntry = $("NoListEntry");
  if (noEntry) {
    noEntry.parentNode.removeChild(noEntry);
  }  
  var li = document.createElement("li");
  li.className = "listEntry";
  li.target = newTarget;
  var close = document.createElement("div");
  close.className = "listClose";
  close.li = li;
  close.onclick = function() {
    var cookie = createCookie("MyPosition-Target-" + this.li.target.id);
    cookie.remove();
    this.li.parentNode.removeChild(this.li);
    saveTargets();
    if ($("TargetsList").childNodes.length == 0) {
      createNoTargetsEntry();
    }
    window.scrollTo(0, 0);
  }  
  li.appendChild(close);
  var text = document.createElement("div");
  text.className = "listTitle";
  text.li = li;
  if (newTarget.name.length > 0) {
    text.innerHTML = newTarget.name;
  }
  else {
    text.innerHTML = "Lat:&nbsp;" + newTarget.lat + "&deg;&nbsp; Long:&nbsp;" + newTarget.lng + "&deg;";
  }  
  text.onclick = function() {
    closeSearch();
    fillNewTarget(this.li.target);
    this.li.parentNode.removeChild(this.li);
    $("TargetsList").insertBefore(this.li, $("TargetsList").firstChild);    
    window.scrollTo(0, 0);
  }
  li.appendChild(text);
  if (first) {
    $("TargetsList").insertBefore(li, $("TargetsList").firstChild);
  }
  else {
    $("TargetsList").appendChild(li);
  }
  saveTargets();
}

function createNoTargetsEntry() {
  var li = document.createElement("li");
  li.className = "listEntry";
  li.id = "NoListEntry";
  li.innerHTML = '<div class="listTitle"><i>No Targets</i></div>';
  $("TargetsList").appendChild(li);  
}

function savePosition() {
  var text = "lat:" + position.lat;
  text += ",lng:" + position.lng;
  text += ",alt:" + position.alt;
  if (position.timeStamp) {
    text += ",timeStamp:" + position.timeStamp;
  }  
  lastCookie.store(text);
}

function getTargetSaveText(theTarget) {
  var text = "name:'" + theTarget.name + "'";
  text += ",lat:" + theTarget.lat;
  text += ",lng:" + theTarget.lng;
  text += ",alt:" + theTarget.alt;
  return text;
}

function saveTarget() {
  targetCookie.store(getTargetSaveText(target));
}

function saveSettings() {
  var text = "isMetric:" + settings.isMetric;
  settingsCookie.store(text);  
}

function saveTargets() {
  var ids = "";
  var lis = $("TargetsList").childNodes;
  for ( var i = 0; i < lis.length; i++) {
    var theTarget = lis[i].target;
    if (i > 0) {
      ids += ",";
    }  
    ids += theTarget.id;    
    var cookie = createCookie("MyPosition-Targets-" + theTarget.id);
    cookie.store(getTargetSaveText(theTarget));
  }
  cookie = createCookie("MyPosition-Targets");
  cookie.store(ids);
}

function loadTargets() {
  targetsCookie = createCookie("MyPosition-Targets");
  if (targetsCookie.get()) {
    try {
      targets = eval("[" + targetsCookie.get() + "]");
      for ( var i = 0; i < targets.length; i++) {
        var id = targets[i];
        var cookie = createCookie("MyPosition-Targets-" + id);
        theTarget = eval("new Object({" + cookie.get() + "})");
        theTarget.id = id;
        if (lastId < id) {
          lastId = id;
        }  
        addTargetToList(theTarget);
      }
    }
    catch(e) {
      alert("Reload failed: " + e);
    }  
  }  
}

function emailLocation() {
  var body="";
  body += "Latitude: " + position.lat;
  body += "<br>Longitude: " + position.lng;
  body += "<br>Altitude: " + position.alt;
  body += "<br><br>Find on map: ";
  body += "http://maps.google.com?q=" + position.lat +
    "%2C" + position.lng + "&ll=" + position.lat + "%2C" + position.lng;  
  phone.sendMail("My Position", body);  
}

function findNameNew() {
  //$("NameSearchValue").value = $("NameNewValue").value;
  $("NewTargetForm").style.display = "none";
  $("NewTargetSearch").style.display = "block";
  //findName();
}

function findName() {
  $("NameSearchValue").style.background = "";
  var search = $("NameSearchValue").value;
  if (search.length == 0) {
    $("NameSearchValue").style.background = "#FFE0E0";
    return;
  };
  $("SearchResults").innerHTML = "Searching...";
  $("LoadingText").innerHTML = "Searching...";
  $("Loading").style.display = "block";
  var url = "http://ws.geonames.org/search?style=FULL&maxRows=10&isNameRequired=true&type=json&callback=searchResults&q=" + encodeURIComponent(search);
  json.call(url, function() {
    $("Loading").style.display = "none";
  },
  function() {
    $("SearchResults").innerHTML = "Request failed!";
    $("Loading").style.display = "none";
  });
}

function searchResults(data) {
  $("SearchResults").innerHTML = "";
  $("Loading").style.display = "none";
  if (data == null) {
    $("SearchResults").innerHTML = "Request failed!";
    return;  
  }
  var names = data.geonames;
  for ( var i = 0; i < names.length; i++) {
    var entry = document.createElement("div");
    entry.innerHTML = names[i].name + ", <i>" + names[i].countryName + "</i>";
    entry.geoName = names[i];
    entry.className = "searchResult";
    entry.onclick = function() {
      $("NameNewValue").value = this.geoName.name;
      $("LatNewValue").value = this.geoName.lat;
      $("LngNewValue").value = this.geoName.lng;
      if (this.geoName.elevation) {
        $("AltNewValue").value = this.geoName.elevation;
      }
      else {
        $("AltNewValue").value = "";
      }  
      closeSearch();
    }  
    $("SearchResults").appendChild(entry);
  }
}

function closeSearch() {
  $("NewTargetForm").style.display = "block";
  $("NewTargetSearch").style.display = "none";
  window.scrollTo(0, 0);
}

function debug(msg) {
  $("Debug").innerHTML = msg + "<br>" + $("Debug").innerHTML;
}

function $(id) {
  return document.getElementById(id);    
}

function tellFriend() {
  var body = "Hi,<br><br>I just stumbled upon this iPhone My Position application:" +
      "<br><br>http://www.itunes.com/app/mypositionapp<br><br>" +
      "Quickly see where and how high you are on earth and get bearing and " +
      "distance to a target." +
      "<br><br>Best regards";
  window.open("mailto:?subject=My Position on the iPhone&body=" + body, "_self");  
}

function orientationChanged() {
  if (window.orientation != undefined) {
    landscape = window.orientation != 0 && window.orientation != 180;
  }
  else {
    landscape = window.innerWidth > window.innerHeight;
  }  
  setTimeout(function() {window.scrollTo(0,0)}, 1);
}
