#ifndef __VEREIGN_CORE_TIME_HH
#define __VEREIGN_CORE_TIME_HH

#include <boost/date_time/posix_time/posix_time.hpp>

namespace vereign::time {

auto Epoch() -> boost::posix_time::ptime {
  static const auto epoch = boost::posix_time::ptime{boost::gregorian::date{1970, 1, 1}};

  return epoch;
}

auto PosixTimeToTime(boost::posix_time::ptime t) -> time_t {
  return time_t((t - Epoch()).total_seconds());
}

auto MakePosixTime(
  int year,
  int month,
  int day,
  int hours,
  int seconds,
  int milliseconds
) -> boost::posix_time::ptime {
  using namespace boost::posix_time;
  using namespace boost::gregorian;

  return ptime(
    date{
      static_cast<date::year_type>(year),
      static_cast<date::month_type>(month),
      static_cast<date::day_type>(day)
    },
    time_duration(hours, seconds, milliseconds)
  );
}

auto MakeTimeUTC(
  int year,
  int month,
  int day,
  int hours,
  int seconds,
  int milliseconds
) -> time_t {
  using namespace boost::posix_time;
  using namespace boost::gregorian;

  return PosixTimeToTime(
    ptime(
      date{
        static_cast<date::year_type>(year),
        static_cast<date::month_type>(month),
        static_cast<date::day_type>(day)
      },
      time_duration(hours, seconds, milliseconds)
    )
  );
}

auto MakeTimeUTCFromString(const std::string& str) -> time_t {
  using namespace boost::posix_time;
  using namespace boost::gregorian;

  return PosixTimeToTime(boost::posix_time::time_from_string(str));
}

auto MakeTimeUTCFromISO(const std::string& str) -> time_t {
  using namespace boost::posix_time;
  using namespace boost::gregorian;

  return PosixTimeToTime(from_iso_string(str));
}

} // vereign::string

#endif // __VEREIGN_CORE_TIME_HH