/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Thomas Bretz  12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
!
!   Copyright: MAGIC Software Development, 2000-2003
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MTime
//
// A generalized MARS time stamp
//
//
// Version 1:
// ----------
//  - first version
//
// Version 2:
// ----------
//  - removed fTimeStamp[2]
//
// Version 3:
// ----------
//  - removed fDurtaion - we may put it back when it is needed
//  - complete rewrite of the data members (old ones completely replaced)
//
/////////////////////////////////////////////////////////////////////////////
#include "MTime.h"

#include <iomanip>
#include <sys/time.h> // struct timeval

#include <TTime.h>

#include "MLog.h"
#include "MAstro.h"

ClassImp(MTime);

using namespace std;

void MTime::GetDate(UShort_t &y, Byte_t &m, Byte_t &d) const
{
    MAstro::Mjd2Ymd((Long_t)fTime<0?fMjd-1:fMjd, y, m, d);
}

Bool_t MTime::Set(UShort_t y, Byte_t m, Byte_t d, Byte_t h, Byte_t min, Byte_t s, UShort_t ms, UInt_t ns)
{
    if (h>23 || min>59 || s>59 || ms>999 || ns>999999)
        return kFALSE;

    const Int_t mjd = MAstro::Ymd2Mjd(y, m, d);
    if (mjd<0)
        return kFALSE;

    const ULong_t tm = ((((h*60+min)*60)+s)*1000)+ms;

    return Set(mjd, tm, ns);
}

void MTime::SetSystemTimer(const struct timeval &tv)
{
    const ULong_t hor = 3600000; // One Hour in milliseconds

    const UInt_t mjd = tv.tv_sec/(60*60*24) + 40587;
    const Long_t tm  = (tv.tv_usec/1000)%(24*hor);

    Set(mjd, tm, tv.tv_usec*1000);
}

void MTime::Now()
{
#ifdef __LINUX__
    struct timeval tv;
    gettimeofday(&tv, NULL);
    SetSystemTimer(tv);
#else
    Reset();
#endif
}

void MTime::Print(Option_t *) const
{
    UShort_t yea, ms;
    Byte_t mon, day, h, m, s;

    GetDate(yea, mon, day);
    GetTime(h, m, s, ms);

    *fLog << GetDescriptor() << ": ";
    *fLog << Form("%4d/%02d/%02d %02d:%02d:%02d.%03d (+%dns)",
                  yea, mon, day, h, m, s, ms, fNanoSec) << endl;
} 
