//Kenneth's Planetarium
//Don't rip this code off.  Not because it's protected, but because it's not finished yet!

//Thanks to http://home.att.net/~srschmitt/script_planet_orbits.html for calculations.  The man's a genius
//Thanks to Sky Telescope for useful skychart reference, to check I'm doing the right things, and some star positions http://skychart.skytonight.com/



//set statics
var DEGS = 180/Math.PI;                  // convert radians to degrees
var RADS = Math.PI/180;                  // convert degrees to radians
var CookieName = "planetarium";
var skyHeight = 500; // may change
var skyWidth = 600; // may change

var stageObjs = [];
var TYPE_BRIGHTSTAR = 0;
var TYPE_STAR = 1;
var TYPE_PLANET = 2;
var TYPE_MOON = 3;

var lat_degrees;
var lat_minutes;
var lon_degrees;
var lon_minutes;
var now;
var dn;

var VIEW_SOUTH = Math.PI / 2;
var VIEW_EAST = Math.PI / 4;
var VIEW_WEST = Math.PI * 3 / 2;
var VIEW_NORTH = 0;

var viewportOffsetR = VIEW_SOUTH;

var myTime = new Date();
var myDayPart = (myTime.getHours() + myTime.getMinutes()/60) / 24;
var realTime = true;

var imageStar = new Image();
imageStar.src = "/blog/wp-content/themes/kenneth/images/star.png";
var imageSun = new Image();
imageSun.src = "/blog/wp-content/themes/kenneth/images/sun.png";
var imageMoon = new Image();
imageMoon.src = "/blog/wp-content/themes/kenneth/images/moon.png";
var imageMercury = new Image();
imageMercury.src = "/blog/wp-content/themes/kenneth/images/mercury.png";
var imageVenus = new Image();
imageVenus.src = "/blog/wp-content/themes/kenneth/images/venus.png";
var imageMars = new Image();
imageMars.src = "/blog/wp-content/themes/kenneth/images/mars.png";
var imageJupiter = new Image();
imageJupiter.src = "/blog/wp-content/themes/kenneth/images/jupiter.png";
var imageSaturn = new Image();
imageSaturn.src = "/blog/wp-content/themes/kenneth/images/saturn.png";
var imageUranus = new Image();
imageUranus.src = "/blog/wp-content/themes/kenneth/images/uranus.png";
var imageNeptune = new Image();
imageNeptune.src = "/blog/wp-content/themes/kenneth/images/neptune.png";
var imagePluto = new Image();
imagePluto.src = "/blog/wp-content/themes/kenneth/images/pluto.png";

setTimes = function() {
    year  = now.getUTCFullYear();
    month = now.getUTCMonth() + 1;
    day   = now.getUTCDate();
    hour  = now.getUTCHours();
    mins  = now.getUTCMinutes();
    secs  = now.getUTCSeconds();
}
    
initializePlanetarium = function() {
    skyHeight = 500; // may change
    skyWidth = $(window).width();

    //CANVAS
    canvas = $("#sky_canvas")[0];
    ctx = canvas.getContext("2d");
    ctx.lineWidth = "2";
    ctx.strokeStyle = "rgb(100, 100, 100)";
    

    lat_degrees = 51;
    lat_minutes = 30;
    lon_degrees = 0;
    lon_minutes = 0;
    lat = dms2real(lat_degrees, lat_minutes, 0);
    lon = dms2real(lon_degrees, lon_minutes, 0);
    //    if (calc.south.checked == true) lat = -lat;
    //    if (calc.west.checked  == true) lon = -lon;  
    
    now	= new Date();
    setTimes();

    // compute day number for date/time
    dn = day_number( year, month, day, hour, mins );

    //get the box to draw in
    planetarium = $("#planetariumDiv")[0];

    //plot the planets, sun and dwarfish pluto 
    var planets = getPlanets();
    for (var i=0;i<planets.length;i++) {
        var starData = planets[i];
        showStar(starData, TYPE_PLANET);
    }
    //plot the moon, man
    var moon = getMoon();
    moon.name = "I am the Moon";
//			moon.ra = moon.ra * DEGS;
//			moon.dec = moon.dec * DEGS;
    showStar(moon, TYPE_MOON);
    //plot the bright stars in the box  (TODO:make them twinkle)
    var brightStarCount = dataBrightStars.brightStars.length;
    for (var i=0;i<brightStarCount;i++) {
        var starData = dataBrightStars.brightStars[i];
        starData.ra = starData.ra * 15;
        starData.dec = 90 - starData.dec;
        showStar(starData, TYPE_BRIGHTSTAR, magnitudeToFrac(starData.magnitude)*10);
    }
    //plot the other stars in the box
    if (!$.browser.msie && $.clientCoords().width>480) {
        // IE CAN'T HANDLE THE UNIVERSE!
        for (var i=0;i<dataStars.stars.length;i++) {
            var starData = dataStars.stars[i];
            starData.ra = starData.ra * 15;
            starData.dec = 90 - starData.dec;
            showStar(starData, TYPE_STAR, magnitudeToFrac(starData.magnitude)*10);
        }
    }

    if ($('#page').hasClass('index')) showAllTimer = setInterval('showAll()',25);
    else reDrawAll(1000, true);
}
var currentTime = (myTime.getHours() + myTime.getMinutes()/60) / 24;
var myWorkingTime = currentTime - 0.3;
if (myWorkingTime<0) myWorkingTime = 0;
var showAllTimer = 0;
function showAll() {
    if (myWorkingTime<currentTime) myWorkingTime+=0.005;
        else clearTimeout(showAllTimer);
    if (myWorkingTime>currentTime) myWorkingTime=currentTime;
    setTime(myWorkingTime);
    reDrawAll(25);
    if (myWorkingTime==currentTime) {
        setTimeout("reDrawAll(500)", 100);
        setTimeout("reDrawAll(1000, true)", 2000);
    }
}
var planetObjs = [];
function showStar(starData, type) {
    if (type==TYPE_BRIGHTSTAR) {
        var starobj = {
            starData: starData,
            redraw : function(showText){
                var position = getSkyPos(this.starData.ra, this.starData.dec);
                ctx.drawImage(imageStar, position.x-2, position.y-53, 7, 7);
                ctx.fillStyle    = '#dde';
                ctx.font         = '10px sans-serif';
                ctx.textBaseline = 'middle';
                if (showText) ctx.fillText(this.starData.name, position.x+6, position.y-51);
            }
        };
        stageObjs[stageObjs.length] = starobj;
        return;
    }
    if (type==TYPE_STAR) {
        var starobj = {
            starData: starData,
            redraw : function(){
                var position = getSkyPos(this.starData.ra, this.starData.dec);
                ctx.fillStyle = "rgb(200,200,200)";
                ctx.fillRect(position.x-2, position.y-53, 2, 2);
            }
        };
        stageObjs[stageObjs.length] = starobj;
//            starobj.redraw();
        return;
    }
    if (type==TYPE_PLANET) {
        var starobj = {
            starData: starData,
            redraw : function(){
                var position = getSkyPos(this.starData.ra, this.starData.dec);
                eval('canvasimage = image'+this.starData.name)
                if (this.starData.name == "Sun") {
                    ctx.drawImage(canvasimage, position.x-100, position.y-153, 234, 216);
                } else {
                    ctx.drawImage(canvasimage, position.x-2, position.y-53, 50, 50);
                }
                ctx.fillStyle    = '#dde';
                ctx.font         = '10px sans-serif';
                ctx.textBaseline = 'middle';
                ctx.fillText(this.starData.name, position.x+6, position.y-51);
            }
        };
        stageObjs[stageObjs.length] = starobj;
        return;
    }
    if (type==TYPE_MOON) {
        var starobj = {
            starData: starData,
            redraw : function(){
                var position = getSkyPos(this.starData.ra, this.starData.dec);
                ctx.drawImage(imageMoon, position.x-2, position.y-53, 75, 75);
                ctx.fillStyle    = '#dde';
                ctx.font         = '10px sans-serif';
                ctx.textBaseline = 'middle';
                ctx.fillText("Moon", position.x+6, position.y-51);
            }
        };
        stageObjs[stageObjs.length] = starobj;
        return;
    }
}

reDrawAll = function(maxDuration, showText) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    meanSiderealTime = mean_sidereal_time(now, lon);
    if (!showText) showText=false;
    var startTime = new Date();
    for (var i=0;i<stageObjs.length;i++) {
        stageObjs[i].redraw(showText);
        if ((new Date())-startTime>maxDuration) break;
    }
}
hideStars = function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (var i=0;i<stageObjs.length;i++) {
        with (stageObjs[i]) {
            if (starData.type!=TYPE_PLANET) {
                style.display = "none";
            }
        }
    }
}
reDrawSun = function() {
    sunObj.redraw();
}
reDrawMoon = function() {
    var moon = getMoon();
    moon.name = "When you are the Moon, ...";
    moon.ra = moon.ra * DEGS;
    moon.dec = moon.dec * DEGS;
    moonObj.starData = moon;
    moonObj.redraw();
}
reDrawPlanets = function() {
    //plot the planets, sun and dwarfish pluto :-P
    var planets = getPlanets();
    for (var i=0;i<planets.length;i++) {
        if (planets[i].name=="Sun") continue;
        planetObjs[planets[i].name].starData = planets[i];
        planetObjs[planets[i].name].redraw();
    }
}



log = function() {
    var out = '';
    for (var i=0;i<arguments.length;i++) out+=arguments[i]+" | ";
    $('log').innerHTML += out+"<br/>";
}

function getSkyPos(ra, dec) {

    var h = new horizon();

    //Convert RA and DEC to alt and az, using the current time, and latlong.
    coord_to_horizon(now, ra, dec, lat, lon, h);
    //alt
    alt = h.alt;
    //az
    az = h.az;
    
//			log(ra, dec, lat, lon, h.alt, h.az);

    // convert to our viewport
    var xPos = 0;
    var yPos = 0;

    // choose viewport angle - important!
    viewportAngleR = Math.PI;
    //view offset (default: looks east)
        //viewportOffsetR = Math.PI / 2;
        //moved to Global var
    // make radians
    azR = (az * RADS) - viewportOffsetR;
    if (azR<0) azR+=Math.PI*2;
    altR = alt * RADS;
    //transform for X
    xPos = (azR * skyWidth / viewportAngleR);
    //transform for Y
    yPos = skyHeight * (1 - 2 * altR  / Math.PI);

    return {"x":xPos, "y":yPos};
}
function magnitudeToFrac(mag) {
    // 1 = max (ie, large negative mag)
    // 0 = invisible (ie, large positive mag)
    mag = Math.abs(mag+2);
    //assuming max of 5.5 (+2);
    mag = 1 - (mag / 7.1);
    //this results in direct scaling - this should really be a logarithmic scale, but this might look better.
    return mag;
}
function setAsync(func, args, delay) {
    if (typeof(window.async)=="undefined") window.async = new Array();
    if (typeof(delay)=="undefined") delay=parseInt(Math.random()*1000);
    var myIndex = window.async.length;
    window.async[myIndex] = {"caller":setAsync.caller, "func":func, "args":args};
    var arglist = "";
    for (var i=0;i<args.length;i++) {
        arglist+="window.async["+myIndex+"].args["+i+"]"+",";
    }
    return setTimeout("window.async["+myIndex+"].func.call(window.async["+myIndex+"].caller,"+arglist.substring(0,arglist.length-1)+")", delay);
}








// altitude, azimuth coordinate structure
function horizon() {
    alt = parseFloat("0");               // altitude [deg]
    az  = parseFloat("0");               // azimuth [deg]
}


//
// compute horizon coordinates from ra, dec, lat, lon, and utc
// ra, dec, lat, lon in  degrees
// utc is a time number in seconds
//
// results returned in h : horizon record structure
//
function coord_to_horizon( utc, ra, dec, lat, lon, h )
{
    var lmst, ha, sin_alt, cos_az, alt, az;

    // compute hour angle in degrees
    ha = meanSiderealTime - ra;
    if (ha < 0) ha = ha + 360;

    // convert degrees to radians
    ha  = ha*RADS;
    dec = dec*RADS;
    lat = lat*RADS;

    // compute altitude in radians
    sin_alt = Math.sin(dec)*Math.sin(lat) + Math.cos(dec)*Math.cos(lat)*Math.cos(ha);
    alt     = Math.asin(sin_alt);

    // compute azimuth in radians
    // divide by zero error at poles or if alt = 90 deg
    cos_az = (Math.sin(dec) - Math.sin(alt)*Math.sin(lat))/(Math.cos(alt)*Math.cos(lat));
    az     = Math.acos(cos_az);

    // convert radians to degrees
    h.alt = alt*DEGS;
    h.az  = az*DEGS;

    // choose hemisphere
    if (Math.sin(ha) > 0) h.az  = 360 - h.az;
}

//
// "mean_sidereal_time" returns the Mean Sidereal Time in units of degrees.
// Use lon = 0 to get the Greenwich MST.
// East longitudes are positive; West longitudes are negative
//
// returns: time in degrees
//
var jd = 0;
function mean_sidereal_time( d, lon )
{
    var year   = d.getUTCFullYear();
    var month  = d.getUTCMonth() + 1;
    var day    = d.getUTCDate();
    var hour   = d.getUTCHours();
    var minute = d.getUTCMinutes();
    var second = d.getUTCSeconds();

    if ((month == 1)||(month == 2))
    {
        year  = year - 1;
        month = month + 12;
    }

    var a = Math.floor(year/100);
    var b = 2 - a + Math.floor(a/4);
    var c = Math.floor(365.25*year);
    var d = Math.floor(30.6001*(month + 1));

    // days since J2000.0
    jd = b + c + d - 730550.5 + day
           + (hour + minute/60.0 + second/3600.0)/24.0;

    // julian centuries since J2000.0
    var jt = jd/36525.0;

    // mean sidereal time
    var mst = 280.46061837 + 360.98564736629*jd
            + 0.000387933*jt*jt - jt*jt*jt/38710000 + lon;

    if (mst > 0.0)
    {
        while (mst > 360.0)
            mst = mst - 360.0;
    }
    else
    {
        while (mst < 0.0)
            mst = mst + 360.0;
    }

    return mst;
}
// day number to/from J2000 (Jan 1.5, 2000)
function day_number( y, m, d, hour, mins )
{
    var h = hour + mins/60;
    var rv = 367*y
           - Math.floor(7*(y + Math.floor((m + 9)/12))/4)
           + Math.floor(275*m/9) + d - 730531.5 + h/24;
    return rv;
}
$.clientCoords = function() {
     var dimensions = {width: 0, height: 0};
     if (document.documentElement) {
         dimensions.width = document.documentElement.offsetWidth;
         dimensions.height = document.documentElement.offsetHeight;
     } else if (window.innerWidth && window.innerHeight) {
         dimensions.width = window.innerWidth;
         dimensions.height = window.innerHeight;
     }
     return dimensions;
}

animateAngleTimer = 0;
function animateAngle() {
    clearTimeout(showAllTimer);
    viewportProgress = viewportProgress + Math.PI/20;
    if (viewportProgress<viewportTarget) {
        viewportOffsetR = viewportProgress % (Math.PI*2);
        reDrawAll(25);
    } else {
        clearTimeout(animateAngleTimer);
        viewportOffsetR = viewportTarget % (Math.PI*2);
        reDrawAll(100, true);
    }
}

function changeAngle() {
    viewportTarget = viewportOffsetR + Math.PI/2;
    viewportProgress = viewportOffsetR;
    animateAngleTimer = setInterval(animateAngle, 50);
    var el = $('#viewPoint')[0];
    if (el.innerHTML=="South") el.innerHTML="West";
    else if (el.innerHTML=="West") el.innerHTML="North";
    else if (el.innerHTML=="North") el.innerHTML="East";
    else if (el.innerHTML=="East") el.innerHTML="South";
}

function getTimeFromFraction(dayPart) {
    //Gets the time from 24hour clock as from a fraction of a day
    var hour = dayPart * 24;
    hour = Math.floor(hour);
    var minute = ((dayPart * 24) - hour) * 60;
    minute = Math.floor(minute);
    if (hour==24) hour=0;
    var myyear = 0;
    if (now) myyear = now.getYear();
    if (myyear<1900) myyear+=1900; 
    if (typeof(year)!="undefined") now = new Date(myyear, now.getMonth(), now.getDate(), hour, minute, secs);
    if (minute<10) minute = "0" + minute;
    return now.getDate() + "/" + (now.getMonth()+1) + "/" + myyear + " " + hour + ":" + minute;
}
function setTime(dayPart) {
    myDayPart = dayPart;
    $('#timeDisplay')[0].innerHTML = getTimeFromFraction(dayPart);
    var myOpacity = (dayPart-0.5)*(dayPart-0.5)*4;
    if (myOpacity>=1) myOpacity = 0.9999;
    $('#night').css('opacity',myOpacity); 
}
function resizeWindow() {
    skyWidth = $(window).width();
    for (var i=0;i<stageObjs.length;i++) {
        stageObjs[i].redraw();
    }

}
