// ALL GOOD STUFF ADAPTED FROM THIS WONDERFUL OLD SITE:
// http://www.stargazing.net/kepler/ellipse.html

// angles are in degrees
// distances are in a.u.

////////////////////////////////////////////

// dates
var dayToMs = 24*60*60*1000;
var msToDay = 1/dayToMs;

// trig
var degToRad = (2*Math.PI)/360;
var radToDeg = 1/degToRad;
function sin(x) { return Math.sin(x * degToRad); }
function cos(x) { return Math.cos(x * degToRad); }

// "Osculating Elements"

var abbrevs = {
  "i": "Inclination",
  "o": "Longitude of the Ascending Node",
  "p": "Longitude of Perihelion",
  "a": "Mean distance",
  "n": "Daily motion",
  "e": "Eccentricity",
  "L": "Mean Longitude",
  "JD": "Julian Date"
}

var earth = {
  "i": 0.00041,
  "o": 349.2,
  "p": 102.8517,
  "a": 1.0000200,
  "n": 0.9855796,
  "e": 0.0166967,
  "L": 328.40353,
  "JD": 2450680.5,
  "datetime": new Date("August 20, 1997 00:00:00"),
  "radius": 0.000042563739
};

var mars = {
  "i": 1.84992,
  "o": 49.5664,
  "p": 336.0882,
  "a": 1.5236365,
  "n": 0.5240613,
  "e": 0.0934231,
  "L": 262.42784,
  "JD": 2450680.5,
  "datetime": new Date("August 20, 1997 00:00:00"),
  "radius": 0.00002263
};

var sun = {
  "radius": 0.004649
}

// MATH

function meanAnomaly(satellite, time) {
  var days = (time-satellite.datetime)*msToDay;
  return ((satellite.n * days + satellite.L - satellite.p) % 360 + 360) % 360;
}

function trueAnomaly(satellite, time) {
  var M = meanAnomaly(satellite, time);
  return M + (180/Math.PI) * 
    (
      (2 * satellite.e - Math.pow(satellite.e, 3)/4) * Math.sin(degToRad*M) +
      (5/4 * Math.pow(satellite.e, 2)) * Math.sin(degToRad*M*2) +
      (13/12 * Math.pow(satellite.e, 3)) * Math.sin(degToRad*M*3)
    );
}

function radius(satellite, time) {
  return satellite.a * (1 - Math.pow(satellite.e, 2)) / (1 + satellite.e * Math.cos(trueAnomaly(satellite, time)*degToRad));
}

function coordinates(satellite, time) {
	var r = radius(satellite, time);
  var v = trueAnomaly(satellite, time);
  var o = satellite.o;
  var p = satellite.p;
  var i = satellite.i;
  
  var X = r * (cos(o) * cos(v+p-o) - sin(o) * sin(v+p-o) * cos(i));
  var Y = r * (sin(o) * cos(v+p-o) + cos(o) * sin(v+p-o) * cos(i));
  var Z = r * (sin(v+p-o) * sin(i));
  
  return [X,Y,Z];
}

// au to pixels
var minPx = Math.min(window.innerHeight, window.innerWidth);
var auScale = d3.scale.linear().domain([0,2.2]).range([0,minPx]);

var sunSel = d3.select("#ecliptic").append("div")
    .classed('celestial-body', true)
		.attr('id', 'sun')
		.style('left', '0')
		.style('top', '0')
		.style('width', (auScale(sun.radius)*2)+'px')
		.style('height', (auScale(sun.radius)*2)+'px');

var earthSel = d3.select("#ecliptic").append("div")
    .classed('celestial-body', true)
		.attr('id', 'earth')
		.style('width', (auScale(earth.radius)*2)+'px')
		.style('height', (auScale(earth.radius)*2)+'px');

function render(time) {
  var earthRadius = radius(earth, time);
  var earthTrueAnomaly = trueAnomaly(earth, time);
  var earthCoords = coordinates(earth, time);
  console.log(earthCoords);
  
  d3.select("#date").text(time);
  d3.select("#radius").text(earthRadius);
  d3.select("#true-anomaly").text(earthTrueAnomaly);
  d3.select("#true-anomaly-pi").text(earthTrueAnomaly*degToRad/Math.PI);
  
  earthSel
    .style('left', auScale(earthCoords[0]) + 'px')
    .style('top', auScale(earthCoords[1]) + 'px')
}
render(new Date());

var realtime = setInterval(function() { render(new Date()); }, 1000);
var fastForward;
window.onclick = function() {
  clearInterval(realtime);
  clearInterval(fastForward);
  var t = 0;
  fastForward = setInterval(function() {
    var newTime = new Date(+new Date() + t*dayToMs);
    render(newTime);
    t++;
  }, 50);
}