//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org> 
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.

//( { file_desc:"Time cand clock related functions." kw: [ time system ] }
//
//
// This interface is used to read the systems high resolution timer and 
// calculate elapsed time.
//)


#ifndef cwTime_H
#define cwTime_H

namespace cw
{
  namespace time
  {

    //(
    typedef  struct timespec spec_t;

    // Get the time 
    void get( spec_t& tRef );
    spec_t current_time(); // same as get()

    // Return the elapsed time (t1 - t0) in microseconds
    // t1 is assumed to be at a later time than t0.
    unsigned long long elapsedMicros( const spec_t&  t0, const spec_t& t1 );
    unsigned long long elapsedMicros( const spec_t&  t0 );

    // Wrapper on elapsedMicros()
    unsigned elapsedMs( const spec_t&  t0, const spec_t& t1 );
    unsigned elapsedMs( const spec_t&  t0 );

    // Wrapper on elapsedMicros()
    double elapsedSecs( const spec_t&  t0, const spec_t& t1 );
    double elapsedSecs( const spec_t&  t0 );

    // Same as elapsedMicros() but the times are not assumed to be ordered.
    // The function therefore begins by swapping t1 and t0 if t0 is after t1.
    unsigned absElapsedMicros( const spec_t&  t0, const spec_t& t1 ); 


    // Same as elapsedMicros() but returns a negative value if t0 is after t1.
    int diffMicros( const spec_t&  t0, const spec_t& t1 );


    // Returns true if t0 <=  t1.
    bool isLTE( const spec_t& t0, const spec_t& t1 );
    
    // Returns true if t0 <  t1.
    bool isLT(  const spec_t& t0, const spec_t& t1 );

    // Return true if t0 >= t1.
    bool isGTE( const spec_t& t0, const spec_t& t1 );
    
   // Return true if t0 > t1. 
   bool isGT(  const spec_t& t0, const spec_t& t1 );

    bool isEqual( const spec_t& t0, const spec_t& t1 );

    bool isZero( const spec_t& t0 );

    void setZero( spec_t& t0 );

    rc_t now( spec_t& ts ); // same as get()

    void subtractMicros( spec_t& ts, unsigned us );
    
    // Advance 'ts' by 'us/'ms' microseconds/milliseconds.
    void advanceMicros( spec_t& ts, unsigned us );
    void advanceMs( spec_t& ts, unsigned ms );

    // Advance the current time by 'ms' milliseconds;
    rc_t futureMs( spec_t& ts, unsigned ms );

    void fracSecondsToSpec(      spec_t& ts, double sec );
    void secondsToSpec(      spec_t& ts, unsigned sec );
    double specToSeconds(  const spec_t& ts );

    unsigned long long specToMicroseconds( const spec_t& ts );

    void millisecondsToSpec( spec_t& ts, unsigned ms );
    void microsecondsToSpec( spec_t& ts, unsigned long long us );
    spec_t microsecondsToSpec( unsigned long long us );

    // Return count of bytes in in buf[]
    unsigned formatDateTime( char* buf, unsigned bufN, bool includeDateFl=false );

    rc_t test( const test::test_args_t& test );

    //)

  }
}

#endif