var MARS_TO_EARTH_DAYS = 1.027491251;
var EPOCH_OFFSET = 587744.77817
var ROUND_UP_SECOND = 1/86400;
var eDaysTilMonth = new Array( -1, -1,
 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333);
var eDaysInMonth = new Array( 0, 31, 29, 31, 30, 31, 30, 31, 31,
 30, 31, 30, 31);

function getEarthDaysFromForm()
{
    var year = parseInt(document.calc.eYear.value, 10);
    var month= parseInt(document.calc.eMonth.value,10);
    var day  = parseInt(document.calc.eDay.value,  10);

    var daysSince = day + eDaysTilMonth[month]
        + 365 * year
        + Math.floor(year / 4)
        - Math.floor(year / 100)
        + Math.floor(year / 400)

    if((month < 3)
      && isEarthLeapYear(year))
        daysSince -= 1;

    var hour = parseInt(document.calc.eHour.value, 10)/24
    var min  = parseInt(document.calc.eMin.value, 10)/1440
    var sec  = parseInt(document.calc.eSec.value, 10)/86400;

    if(!isNaN(hour)) daysSince += hour;
    if(!isNaN(min))  daysSince += min;
    if(!isNaN(sec))  daysSince += sec;

    return daysSince;
}


function getMarsSolsFromForm()
{
    var year = parseInt(document.calc.mYear.value, 10);
    var month= parseInt(document.calc.mMonth.value,10);
    var day  = parseInt(document.calc.mDay.value,  10);
    var TestData = 3;

    var solsSince = day + ((month-1) * 28) - Math.floor((month-1)/6)
        + 668 * year
          + Math.floor(year / 2)
          + Math.floor((year-1) / 10)
          - Math.floor((year-1) / 100)
          + Math.floor((year-1) / 1000);

    var hour = parseInt(document.calc.mHour.value, 10)/24
    var min  = parseInt(document.calc.mMin.value, 10)/1440
    var sec  = parseInt(document.calc.mSec.value, 10)/86400;

    if(!isNaN(hour)) solsSince += hour;
    if(!isNaN(min))  solsSince += min;
    if(!isNaN(sec))  solsSince += sec;

    return solsSince;
}

function setMarsDateFromSols(solsSince)
{
    // get the fractional part, to do the time later
    partialSol = solsSince - Math.floor(solsSince);

    // Convert sols to Martian date:
    var s = solsSince;
 
    var sD  = Math.floor(s/334296);
    var doD = Math.floor(s-(sD*334296));
 
    var sC = 0;
    var doC = doD;
    if(doD != 0) sC = Math.floor((doD-1)/66859);
    if(sC != 0) doC -= (sC*66859+1);

    var sX = 0;
    var doX = doC;
    if(sC != 0)  // century that does not begin with leap day
    {
      sX = Math.floor((doC+1)/6686);
      if(sX != 0) doX -= (sX*6686-1);
    }
    else
    {
      sX = Math.floor(doC/6686);
      if(sX != 0) doX -= (sX*6686);
    }

    var sII = 0;
    var doII = doX;
    if(sC != 0 && sX == 0)  // decade that does not begin with leap day
    {
      sII = Math.floor(doX/1337);
      if(sII != 0) doII -= (sII*1337);
    }
    else  // 1338, 1337, 1337, 1337 ...
    {
      if(doX != 0) sII = Math.floor((doX-1)/1337);
      if(sII != 0) doII -= (sII*1337+1);
    }

    var sI = 0;
    var doI= doII;
    if(sII==0 && (sX != 0 || (sX == 0 && sC == 0)))
    {
      sI = Math.floor(doII/669);
      if(sI != 0) doI -= 669;
    }
    else  // 668, 669
    {
      sI = Math.floor((doII+1)/669);
      if(sI != 0) doI -= 668;
    }

    marsYear = 500*sD + 100*sC + 10*sX + 2*sII + sI;


    // get the date from the day of the year:

    var tmpSeason = getMartianSeasonFromSol(doI);            // 0-3
    var tmpSolOfSeason = doI-167*tmpSeason;                  // 0-167
    var tmpMonthOfSeason = Math.floor(tmpSolOfSeason/28);    // 0-5

    var marsMonth = tmpMonthOfSeason + 6*tmpSeason + 1;      // 1-24

    var marsDay   = doI - ((marsMonth-1)*28 - tmpSeason) + 1;  // 1-28

    var SolNomen = parseInt(document.calc.InSolNomen.value, 10);

    if (SolNomen == 1)
    {
    //Darian Sols of the Week
    if ((marsDay - 1) % 7 + 1 == 1)
    	nSolName = "Sol Solis";
    if ((marsDay - 1) % 7 + 1 == 2)
    	nSolName = "Sol Lunae";
    if ((marsDay - 1) % 7 + 1 == 3)
    	nSolName = "Sol Martis";
    if ((marsDay - 1) % 7 + 1 == 4)
    	nSolName = "Sol Mercurii";
    if ((marsDay - 1) % 7 + 1 == 5)
    	nSolName = "Sol Jovis";
    if ((marsDay - 1) % 7 + 1 == 6)
    	nSolName = "Sol Veneris";
    if ((marsDay - 1) % 7 + 1 == 7)
    	nSolName = "Sol Saturni";
    }

    else if (SolNomen == 2)
    {
    //Darian Defrost Sols of the Week
    if ((marsDay - 1) % 7 + 1 == 1)
    	nSolName = "Axatisol";
    if ((marsDay - 1) % 7 + 1 == 2)
    	nSolName = "Benasol";
    if ((marsDay - 1) % 7 + 1 == 3)
    	nSolName = "Ciposol";
    if ((marsDay - 1) % 7 + 1 == 4)
    	nSolName = "Domesol";
    if ((marsDay - 1) % 7 + 1 == 5)
    	nSolName = "Erjasol";
    if ((marsDay - 1) % 7 + 1 == 6)
    	nSolName = "Fulisol";
    if ((marsDay - 1) % 7 + 1 == 7)
    	nSolName = "Gavisol";
    }

    else if (SolNomen == 3)
    {

    //Utopian Sols of the Week
    if ((marsDay - 1) % 7 + 1 == 1)
    	nSolName = "Sunsol";
    if ((marsDay - 1) % 7 + 1 == 2)
    	nSolName = "Phobosol";
    if ((marsDay - 1) % 7 + 1 == 3)
    	nSolName = "Deimosol";
    if ((marsDay - 1) % 7 + 1 == 4)
    	nSolName = "Terrasol";
    if ((marsDay - 1) % 7 + 1 == 5)
    	nSolName = "Venusol";
    if ((marsDay - 1) % 7 + 1 == 6)
    	nSolName = "Mercurisol";
    if ((marsDay - 1) % 7 + 1 == 7)
    	nSolName = "Jovisol";
    }

    // Put the result up:

    document.calc.mYear.value = threeDigit(marsYear);
    document.calc.mMonth.value = marsMonth;
    document.calc.mDay.value = twoDigit(marsDay);
    document.calc.mJulianDay.value = (Math.floor(solsSince*100000)/100000);
    document.calc.mNumDay.value = threeDigit(doI);
    document.calc.mSolName.value = nSolName;

    var tmpHour = partialSol*24;
    var tmpMin  = (tmpHour - Math.floor(tmpHour))*60;
    var tmpSec  = (tmpMin - Math.floor(tmpMin))*60;
    document.calc.mHour.value = twoDigit(Math.floor(tmpHour));
    document.calc.mMin.value  = twoDigit(tmpMin);
    document.calc.mSec.value  = twoDigit(tmpSec);

    var OrbitPlot = parseInt(document.calc.InOrbitPlot.value, 10);

    if (OrbitPlot == 1)
    {
	// convert sols to Ls:
	MarsSolNum = doI + 1;
	// Sagittarius
	if (MarsSolNum > 0 && MarsSolNum <= 28)
		LsMars = 15 / 28 * MarsSolNum;
	// Dhanus
	if (MarsSolNum > 28 && MarsSolNum <= 56)
		LsMars = (29.5 - 15) / 28 * (MarsSolNum - 28) + 15;
	// Capricornus
	if (MarsSolNum > 56 && MarsSolNum <= 84)
		LsMars = (44.5 - 29.5) / 28 * (MarsSolNum - 56) + 29.5;
	// Makara
	if (MarsSolNum > 84 && MarsSolNum <= 112)
		LsMars = (58.5 - 44.5) / 28 * (MarsSolNum - 84) + 44.5;
	// Aquarius
	if (MarsSolNum > 112 && MarsSolNum <= 140)
		LsMars = (72 - 58.5) / 28 * (MarsSolNum - 112) + 58.5;
	// Kumbha
	if (MarsSolNum > 140 && MarsSolNum <= 167)
		LsMars = (85 - 72) / 27 * (MarsSolNum - 140) + 72;
	// Pisces
	if (MarsSolNum > 167 && MarsSolNum <= 195)
		LsMars = (97 - 85) / 28 * (MarsSolNum - 167) + 85;
	// Mina
	if (MarsSolNum > 195 && MarsSolNum <= 223)
		LsMars = (110.5 - 97) / 28 * (MarsSolNum - 195) + 97;
	// Aries
	if (MarsSolNum > 223 && MarsSolNum <= 251)
		LsMars = (124 - 110.5) / 28 * (MarsSolNum - 223) + 110.5;
	// Mesha
	if (MarsSolNum > 251 && MarsSolNum <= 279)
		LsMars = (139 - 124) / 28 * (MarsSolNum - 251) + 124;
	// Taurus
	if (MarsSolNum > 279 && MarsSolNum <= 307)
		LsMars = (154.5 - 139) / 28 * (MarsSolNum - 279) + 139;
	// Rishabha
	if (MarsSolNum > 307 && MarsSolNum <= 334)
		LsMars = (170 - 154.5) / 27 * (MarsSolNum - 307) + 154.5;
	// Gemini
	if (MarsSolNum > 334 && MarsSolNum <= 362)
		LsMars = (184.5 - 170) / 28 * (MarsSolNum - 334) + 170;
	// Mithuna
	if (MarsSolNum > 362 && MarsSolNum <= 390)
		LsMars = (200.5 - 184.5) / 28 * (MarsSolNum - 362) + 184.5;
	// Cancer
	if (MarsSolNum > 390 && MarsSolNum <= 418)
		LsMars = (216 - 200.5) / 28 * (MarsSolNum - 390) + 200.5;
	// Karka
	if (MarsSolNum > 418 && MarsSolNum <= 446)
		LsMars = (234 - 216) / 28 * (MarsSolNum - 418) + 216;
	// Leo
	if (MarsSolNum > 446 && MarsSolNum <= 474)
		LsMars = (248 - 234) / 28 * (MarsSolNum - 446) + 234;
	// Simha
	if (MarsSolNum > 474 && MarsSolNum <= 501)
		LsMars = (265 - 248) / 27 * (MarsSolNum - 474) + 248;
	// Virgo
	if (MarsSolNum > 501 && MarsSolNum <= 529)
		LsMars = (282.5 - 265) / 28 * (MarsSolNum - 501) + 265;
	// Kanya
	if (MarsSolNum > 529 && MarsSolNum <= 557)
		LsMars = (297.5 - 282.5) / 28 * (MarsSolNum - 529) + 282.5;
	// Libra
	if (MarsSolNum > 557 && MarsSolNum <= 585)
		LsMars = (312 - 297.5) / 28 * (MarsSolNum - 557) + 297.5;
	// Tula
	if (MarsSolNum > 585 && MarsSolNum <= 613)
		LsMars = (329 - 312) / 28 * (MarsSolNum - 585) + 312;
	// Scorpius
	if (MarsSolNum > 613 && MarsSolNum <= 641)
		LsMars = (345.5 - 329) / 28 * (MarsSolNum - 613) + 329;
	// Vrishika
	if (MarsSolNum > 641 && MarsSolNum <= 669)
		LsMars = (360 - 345.5) / 28 * (MarsSolNum - 641) + 345.5;

	obs = new Array(2);
	obs[2]=new Array (eval('ob'+2).style,-100,-100);

	obs[2][0].left= -Math.sin((LsMars - 9.5) * Math.PI / 180) * 166 + 4;
	obs[2][0].top= -Math.cos((LsMars - 9.5) * Math.PI / 180) * 177 - 240;
    }
}

function setEarthDateFromDays(daysSince)
{
    // get the fractional part, to do the time later
    partialDay = daysSince - Math.floor(daysSince);

    // Convert days to Gregorian date:

    var d = Math.floor(daysSince)+1;

    var sCD = Math.floor(d/146097);   // what 400 year span
    var doCD= Math.floor(d-(sCD*146097));

    var sC = 0;
    var doC = doCD;
    if(doCD != 0) sC = Math.floor((doCD-1)/36524);
    if(sC != 0) doC -= (sC*36524+1);

    var sIV = 0;
    var doIV = doC;
    if(sC != 0)  // 1460 + 1461*24
    {
      sIV = Math.floor((doC+1)/1461);
      if(sIV != 0) doIV -= (sIV*1461-1);
    }
    else  // 1461*25
    {
      sIV = Math.floor(doC/1461);
      if(sIV != 0) doIV -= (sIV*1461);
    }

    var sI = 0;
    var doI = doIV;
    if(sC != 0 && sIV == 0)  // four 365-day years in a row
    {
      sI = Math.floor(doIV/365);
      if(sI != 0) doI -= (sI*365);
    }
    else   // normal leap year cycle
    {
      if(doI != 0) sI = Math.floor((doIV-1)/365);
      if(sI != 0) doI -= (sI*365 + 1);
    }

    earthYear = 400*sCD + 100*sC + 4*sIV + sI;
    var tmpDayOfYear = doI+1;

    for(i=1; i<12; i++)
    {
        var tmpDaysInMonth = eDaysInMonth[i];
        if(i==2 && !isEarthLeapYear(earthYear))
            tmpDaysInMonth -= 1;

        if(tmpDayOfYear > tmpDaysInMonth)
            tmpDayOfYear -= tmpDaysInMonth;
        else
            break;
    }

    earthMonth = i;
    earthDay = tmpDayOfYear;

    if ((Math.floor(daysSince) + 1) % 7 == 1)
    	nDayName = "Sunday";
    if ((Math.floor(daysSince) + 1) % 7 == 2)
    	nDayName = "Monday";
    if ((Math.floor(daysSince) + 1) % 7 == 3)
    	nDayName = "Tuesday";
    if ((Math.floor(daysSince) + 1) % 7 == 4)
    	nDayName = "Wednesday";
    if ((Math.floor(daysSince) + 1) % 7 == 5)
    	nDayName = "Thursday";
    if ((Math.floor(daysSince) + 1) % 7 == 6)
    	nDayName = "Friday";
    if ((Math.floor(daysSince) + 1) % 7 == 7)
    	nDayName = "Saturday";

    // Put the result up:

    document.calc.eYear.value = earthYear;
    document.calc.eMonth.value = earthMonth;
    document.calc.eDay.value = twoDigit(earthDay);
    document.calc.eJulianDay.value = (Math.floor(daysSince*100000)/100000) + 1721060.5;
    document.calc.eNumDay.value = threeDigit(doI + 1);
    document.calc.eDayName.value = nDayName;

    var tmpHour = partialDay*24;
    var tmpMin  = (tmpHour - Math.floor(tmpHour))*60;
    var tmpSec  = (tmpMin - Math.floor(tmpMin))*60;
    document.calc.eHour.value = twoDigit(Math.floor(tmpHour));
    document.calc.eMin.value  = twoDigit(tmpMin);
    document.calc.eSec.value  = twoDigit(tmpSec);

    var OrbitPlot = parseInt(document.calc.InOrbitPlot.value, 10);

    if (OrbitPlot == 1)
    {
	if (earthYear % 4 == 0)
		LeapDay = 1;
	else
		LeapDay = 0;
	
	if (earthMonth == 1)
		EarthDayNum = earthDay;
	if (earthMonth == 2)
		EarthDayNum = earthDay + 31;
	if (earthMonth == 3)
		EarthDayNum = earthDay + 59 + LeapDay;
	if (earthMonth == 4)
		EarthDayNum = earthDay + 90 + LeapDay;
	if (earthMonth == 5)
		EarthDayNum = earthDay + 120 + LeapDay;
	if (earthMonth == 6)
		EarthDayNum = earthDay + 151 + LeapDay;
	if (earthMonth == 7)
		EarthDayNum = earthDay + 181 + LeapDay;
	if (earthMonth == 8)
		EarthDayNum = earthDay + 212 + LeapDay;
	if (earthMonth == 9)
		EarthDayNum = earthDay + 243 + LeapDay;
	if (earthMonth == 10)
		EarthDayNum = earthDay + 273 + LeapDay;
	if (earthMonth == 11)
		EarthDayNum = earthDay + 304 + LeapDay;
	if (earthMonth == 12)
		EarthDayNum = earthDay + 334 + LeapDay;

	LsEarth= (EarthDayNum - 83) * 360/365;

	obs = new Array(2);
	obs[1]=new Array (eval('ob'+1).style,-100,-100);

	obs[1][0].left= -Math.cos(LsEarth * Math.PI / 180) * 108 + 17;
	obs[1][0].top= Math.sin(LsEarth * Math.PI / 180) * 116 - 209;
    }
}


function convEarthToMars()
{
    var daysSince, solsSince, partialSol;
    var marsYear, marsMonth, marsDay;

    // Range checking:

    if(document.calc.eYear.value < 0)
    {
        alert("Warning: Dates before the year 1 are not handled exactly by this applet.");
    }
    else if(document.calc.eYear.value < 1582)
    {
        alert("Warning: Gregorian calendar did not exist in the year specified.");
    }
    else if(document.calc.eYear.value < 1753)
    {
        alert("Warning: The British Empire did not adopt the Gregorian calendar until 1752.");
    }

    if(document.calc.eMonth.value < 1
     || document.calc.eMonth.value > 12)
    {
        alert("There are not that many months on Earth.");
        return;
    }

    if(document.calc.eDay.value < 1
     || document.calc.eDay.value > eDaysInMonth[document.calc.eMonth.value]
     || (!isEarthLeapYear(document.calc.eYear.value)
       && document.calc.eMonth.value==2
       && document.calc.eDay.value > 28))
    {
        alert("There are not that many days in this month on Earth.");
        return;
    }

    // Convert to straight days:

    daysSince = getEarthDaysFromForm();

//    if(document.calc.eTZ.options[document.calc.eTZ.selectedIndex].text == "Local")
      daysSince += (new Date()).getTimezoneOffset()/1440;
//    else
//      daysSince +=
//        document.calc.eTZ.options[document.calc.eTZ.selectedIndex].value/1440;

    // Convert days to sols:

    solsSince = (daysSince - EPOCH_OFFSET) / MARS_TO_EARTH_DAYS;

//    solsSince +=
//      document.calc.mTZ.options[document.calc.mTZ.selectedIndex].value/360;

    // Convert back to date, and put it it form:
    setMarsDateFromSols(solsSince);
    setEarthDateFromDays(daysSince);
}

function convMarsToEarth()
{
    var solsSince, daysSince, partialDay;
    var eYear, eMonth, eDay;

    // Range checking:
    if(document.calc.mMonth.value < 1
     || document.calc.mMonth.value > 24)
    {
        alert("There are not that many months on Mars.");
        return;
    }

    if(document.calc.mDay.value < 1
     || document.calc.mDay.value > 28
     || (document.calc.mMonth.value % 6 == 0
       && document.calc.mDay.value == 28
       && !(document.calc.mMonth.value == 24
         && isMartianLeapYear(document.calc.mYear.value))))
    {
        alert("There are not that many days in this month on Mars.");
        return;
    }

    // Convert Martian date to sols:

    solsSince = getMarsSolsFromForm();

//    solsSince -=
//      document.calc.mTZ.options[document.calc.mTZ.selectedIndex].value/360;

    // Convert sols to days:

    daysSince = solsSince*MARS_TO_EARTH_DAYS + EPOCH_OFFSET
      + ROUND_UP_SECOND;

//    if(document.calc.eTZ.options[document.calc.eTZ.selectedIndex].text == "Local")
      daysSince -= (new Date()).getTimezoneOffset()/1440;
//    else
//      daysSince -=
//        document.calc.eTZ.options[document.calc.eTZ.selectedIndex].value/1440;

    // Convert back to date, and put it it form:
    setEarthDateFromDays(daysSince);
    setMarsDateFromSols(solsSince);
}

function daysInEarthYear(year)
{
    if(isEarthLeapYear(year)) return 366;
    else return 365;
}

function isEarthLeapYear(year)
{
    if((year % 400) == 0) return true;
    if((year % 100) == 0) return false;
    if((year %   4) == 0) return true;
    return false;
}

function getMartianSeasonFromSol(sol)
  {
    if(sol < 167) return 0;
    if(sol < 334) return 1;
    if(sol < 501) return 2;
    return 3;
  }

function daysInMartianYear(year)
{
    if(isMartianLeapYear(year)) return 669;
    else return 668;
}

function isMartianLeapYear(year)
{
    if((year % 500) == 0) return true;
    if((year % 100) == 0) return false;
    if((year %  10) == 0) return true;
    if((year %   2) == 0) return false;
    return true;
}

function twoDigit(n)
{
  if(n<10) return "0"+Math.floor(n);
  else return Math.floor(n);
}

function threeDigit(n)
{
	if (n < 0)
		return "-" + PadLeft(-n, 3, "0");
	else
		return PadLeft(n, 3, "0");
}

// functions to add characters to start of a string until desired length reached:
function PadLeft(value, width, chPad)
{
	// convert to a string:
	var result = value + "";
	// add pad characters until desired width is reached:
	while (result.length < width)
		result = chPad + result;
	return result;
}

function insertNow()
{
    d = new Date();

    document.calc.eYear.value = d.getUTCFullYear();
    document.calc.eMonth.value= d.getUTCMonth() + 1;
    document.calc.eDay.value  = twoDigit(d.getUTCDate());
    document.calc.eHour.value = d.getUTCHours();
    document.calc.eMin.value  = twoDigit(d.getMinutes());
    document.calc.eSec.value  = twoDigit(d.getSeconds());
//    document.calc.eTZ.selectedIndex = 0;    // set Time Zone to local

    convEarthToMars();
}


