#include "timer.h"

#include <stdio.h>
#include <iostream.h>

#include "math.h"           // modf
#include "sys/time.h"       // struct timeval
#include "slalib/slalib.h"  // slacldj

void Timer::SetTimer(int tv_sec, double tv_usec)
{
    fSecs = tv_sec;
    fMs = tv_usec;

    fSec  = tv_sec%60;
    tv_sec /= 60;

    fMin = tv_sec%60;
    tv_sec /= 60;

    fHor = tv_sec%24;
    tv_sec /= 24;

    fDay = tv_sec%365;
    tv_sec /= 365;

    fYea = tv_sec+1970;

    fDay -= (fYea-1972)/4;

    int days = fDay;

    fMon=0;
    do fDay -= fDays[fMon++];
    while (fDay>0);

    int i=1;
    while (i<fMon)
        days -= fDays[i++];

    fDay = days;

    double dummy;
    fDiv = modf((fMs+fSecs)/(60*60*24), &dummy);
}

void Timer::SetTimer(const struct timeval *tv)
{
    SetTimer(tv->tv_sec, (double)tv->tv_usec/1000000.0);
}

Timer::Timer(double t)
{
    double inte;
    double frac = modf(t, &inte);
    SetTimer(inte, frac);
}

Timer::Timer(struct timeval *tv)
{
    SetTimer(tv);
}

Timer::Timer(Timer &t)
{
    fMs   = t.fMs;
    fDiv  = t.fDiv;
    fSec  = t.fSec;
    fSecs = t.fSecs;
    fMin  = t.fMin;
    fHor  = t.fHor;
    fDay  = t.fDay;
    fMon  = t.fMon;
    fYea  = t.fYea;
}

double Timer::Now() //[s]
{
    struct timeval tv;
    gettimeofday(&tv, NULL);

    SetTimer(&tv);

    return fMs+fSecs;
}

double Timer::CalcMjd()
{
    int status;
    double mjd=0;
    slaCldj(fYea, fMon, fDay, &mjd, &status);

    if (status)
        cout << "Warning: slaCldj returned " << status << endl;

    return mjd + fDiv;
}

Timer::operator double() //[s]
{
    return fMs+fSecs;
}

void Timer::Print()
{
    cout << fSec << "s +" << fMs << "s" << endl;
}

const char *Timer::GetTimeStr()
{
    sprintf(fDateStr, "%d/%02d/%02d %d:%02d:%02d.%06li",
            fYea, fMon, fDay, fHor, fMin, fSec, (long)(1000000.0*fMs));

    return fDateStr;
}

const int Timer::fDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
