/* Blinker
   Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org>
   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
   a blinkenarea.org project */

#ifndef BLINKER_TIME_H
#define BLINKER_TIME_H

#include <stdint.h>
#include <string>
#include <sys/time.h>
#include <time.h>

namespace Blinker {

/// time, either point in time or duration
class Time
{
public:
  static const Time zero; ///< zero time

public:
  /**
   * @brief get current time
   * @return current time
   */
  static Time now();

public:
  /// constructor
  Time();

  /**
   * @brief constructor from seconds
   * @param[in] t time in seconds
   */
  Time(time_t t);

public:
  /// comparison
  //@{
  int compare(const Time &that) const;
  bool operator==(const Time &that) const;
  bool operator!=(const Time &that) const;
  bool operator<(const Time &that) const;
  bool operator>(const Time &that) const;
  bool operator<=(const Time &that) const;
  bool operator>=(const Time &that) const;
  //@}

  /// arithmetic
  //@{
  const Time & operator+=(const Time &that);
  const Time & operator-=(const Time &that);
  Time operator+(const Time &that) const;
  Time operator-(const Time &that) const;
  //@}

  /**
   * @brief convert from floating point seconds
   * @param[in] s time in seconds
   */
  void fromFloatSec(float s);

  /**
   * @brief convert from milliseconds
   * @param[in] ms milliseconds
   */
  void fromMs(int ms);

  /**
   * @brief convert to seconds
   * @return seconds
   */
  time_t toSec() const;

  /**
   * @brief convert to floating point seconds
   * @return time in seconds
   */
  float toFloatSec() const;

  /**
   * @brief convert to struct timeval
   * @param[out] tv struct timeval
   */
  void toTimeval(struct timeval &tv) const;

  /**
   * @brief convert to human-readable string
   * @return human-readable string
   */
  std::string toStr() const;

public:
  /// sleep for duration
  void sleepFor() const;

  /// sleep until time
  void sleepUntil() const;

protected:
  /// fix internal time representation after calculation
  void fix();

protected:
public:
  int64_t m_sec; ///< seconds
  int64_t m_ns;  ///< nanoseconds
}; // class Time

} // namespace Blinker

#endif // #ifndef BLINKER_TIME_H

