#include "astro.h"


char*   month[] =
{
       "January",
       "February",
       "March",
       "April",
       "May",
       "June",
       "July",
       "August",
       "September",
       "October",
       "November",
       "December",
};

double
dsrc(double d, Tim *t, int i)
{
       double y;

       do {
               t->ifa[i] += 1.;
               y = convdate(t);
       } while(d >= y);
       do {
               t->ifa[i] -= 1.;
               y = convdate(t);
       } while(d < y);
       return d - y;
}

void
dtsetup(double d, Tim *t)
{
       double v;

       t->ifa[0] = floor(1900 + d/365.24220);
       t->ifa[1] = 1;
       t->ifa[2] = 1;
       t->ifa[3] = 0;
       t->ifa[4] = 0;
       t->ifa[1] = floor(1 + dsrc(d, t, 0)/30);
       t->ifa[2] = floor(1 + dsrc(d, t, 1));
       dsrc(d, t, 2);

       v = (d - convdate(t)) * 24;
       t->ifa[3] = floor(v);
       t->ifa[4] = (v - t->ifa[3]) * 60;
       convdate(t);    /* to set timezone */
}

void
pdate(double d)
{
       int i;
       Tim t;

       dtsetup(d, &t);
       if(flags['s']) {
               i = t.ifa[1];
               print("%s ", month[i-1]);
               i = t.ifa[2];
               numb(i);
               print("...");
               return;
       }

       /* year month day */
       print("%4d %2d %2d",
               (int)t.ifa[0],
               (int)t.ifa[1],
               (int)t.ifa[2]);
}

void
ptime(double d)
{
       int h, m, s;
       char *mer;
       Tim t;

       if(flags['s']) {
               /* hour minute */
               dtsetup(d + .5/(24*60), &t);
               h = t.ifa[3];
               m = floor(t.ifa[4]);

               mer = "AM";
               if(h >= 12) {
                       mer = "PM";
                       h -= 12;
               }
               if(h == 0)
                       h = 12;
               numb(h);
               if(m < 10) {
                       if(m == 0) {
                               print("%s exactly ...", mer);
                               return;
                       }
                       print("O ");
               }
               numb(m);
               print("%s ...", mer);
               return;
       }
       /* hour minute second */
       dtsetup(d, &t);
       h = t.ifa[3];
       m = floor(t.ifa[4]);
       s = floor((t.ifa[4]-m) * 60);
       print("%.2d:%.2d:%.2d %.*s", h, m, s, utfnlen(t.tz, 3), t.tz);
}

char*   unit[] =
{
       "zero",
       "one",
       "two",
       "three",
       "four",
       "five",
       "six",
       "seven",
       "eight",
       "nine",
       "ten",
       "eleven",
       "twelve",
       "thirteen",
       "fourteen",
       "fifteen",
       "sixteen",
       "seventeen",
       "eighteen",
       "nineteen"
};
char*   decade[] =
{
       "twenty",
       "thirty",
       "forty",
       "fifty",
       "sixty",
       "seventy",
       "eighty",
       "ninety"
};

void
pstime(double d)
{

       setime(d);

       semi = 0;
       motion = 0;
       rad = 1.e9;
       lambda = 0;
       beta = 0;

// uses lambda, beta, rad, motion
// sets alpha, delta, rp

       helio();

// uses alpha, delta, rp
// sets ra, decl, lha, decl2, az, el

       geo();

       print(" %R %D %D %4.0f", lha, nlat, awlong, elev/3.28084);
}

void
numb(int n)
{

       if(n >= 100) {
               print("%d ", n);
               return;
       }
       if(n >= 20) {
               print("%s ", decade[n/10 - 2]);
               n %= 10;
               if(n == 0)
                       return;
       }
       print("%s ", unit[n]);
}

double
tzone(double y, Tim *z)
{
       double t, l1, l2;
       Tm t1, t2;

       /*
        * get a rough approximation to unix mean time
        */
       t = (y - 25567.5) * 86400;

       /*
        * if outside unix conversions,
        * just call it GMT
        */
       if(t < 0 || t > 2.1e9)
               return y;

       /*
        * convert by both local and gmt
        */
       t1 = *localtime((long)t);
       t2 = *gmtime((long)t);

       /*
        * pick up year crossings
        */
       if(t1.yday == 0 && t2.yday > 1)
               t1.yday = t2.yday+1;
       if(t2.yday == 0 && t1.yday > 1)
               t2.yday = t1.yday+1;

       /*
        * convert times to days
        */
       l1 = t1.yday + t1.hour/24. + t1.min/1440. + t1.sec/86400.;
       l2 = t2.yday + t2.hour/24. + t2.min/1440. + t2.sec/86400.;

       /*
        * return difference
        */
       strncpy(z->tz, t1.zone, sizeof(z->tz));
       return y + (l2 - l1);
}

int     dmo[12] =
{
       0,
       31,
       59,
       90,
       120,
       151,
       181,
       212,
       243,
       273,
       304,
       334
};

/*
* input date conversion
* output is done by zero crossing
* on this input conversion.
*/
double
convdate(Tim *t)
{
       double y, d;
       int m;

       y = t->ifa[0];
       m = t->ifa[1];
       d = t->ifa[2];

       /*
        * normalize the month
        */
       while(m < 1) {
               m += 12;
               y -= 1;
       }
       while(m > 12) {
               m -= 12;
               y += 1;
       }

       /*
        * bc correction
        */
       if(y < 0)
               y += 1;

       /*
        * normal conversion
        */
       y += 4712;
       if(fmod(y, 4) == 0 && m > 2)
               d += 1;
       y = y*365 + floor((y+3)/4) + dmo[m-1] + d - 1;

       /*
        * gregorian change
        */
       if(y > 2361232)
               y -= floor((y-1794167)/36524.220) -
                       floor((y-1721117)/146100);
       y += t->ifa[3]/24 + t->ifa[4]/1440 - 2415020.5;

       /*
        * kitchen clock correction
        */
       strncpy(t->tz, "GMT", sizeof(t->tz));
       if(flags['k'])
               y = tzone(y, t);
       return y;
}