#ifndef TABLEAU_HYPER_IMPL_TIMESTAMP_IMPL_HPP
#define TABLEAU_HYPER_IMPL_TIMESTAMP_IMPL_HPP

#include <hyperapi/hyperapi.h>

namespace hyperapi {
inline Timestamp::Timestamp(Date date, Time time) noexcept
   : date_(std::move(date)), time_(std::move(time)) {
   representation_ = this->date_.getRaw() * microseconds_per_day + this->time_.getRaw();
}

inline Timestamp::Timestamp(hyper_timestamp_t rawTimestamp, raw_t) noexcept
   : representation_(rawTimestamp) {
   date_ = hyperapi::Date(static_cast<hyper_date_t>(representation_ / microseconds_per_day), Date::raw_t());
   time_ = hyperapi::Time(static_cast<hyper_time_t>(representation_ % microseconds_per_day), Time::raw_t());
}

inline hyper_timestamp_t Timestamp::getRaw() const noexcept {
   return representation_;
}

inline const Date& Timestamp::getDate() const noexcept {
   return date_;
}

inline const Time& Timestamp::getTime() const noexcept {
   return time_;
}

inline std::string Timestamp::toString() const {
   return getDate().toString() + ' ' + getTime().toString();
}

inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) noexcept {
   return lhs.representation_ == rhs.representation_;
}

inline bool operator>(const Timestamp& lhs, const Timestamp& rhs) noexcept {
   return lhs.representation_ > rhs.representation_;
}
}

namespace std {
/** Specialization of `std::hash` for `hyperapi::Timestamp`. */
template <>
struct hash<hyperapi::Timestamp> {
   /** Calculates the hash value of the given timestamp. */
   size_t operator()(const hyperapi::Timestamp& timestamp) const noexcept { return timestamp.getRaw(); }
};
}
#endif
