#pragma once

#include <cstdint>
#include <string>
#include <array>
#include <chrono>

namespace systime
{

struct DateTimeStruct
{
	uint16_t year;
	uint8_t month;
	uint8_t date;
	uint8_t hour;
	uint8_t minute;
	uint8_t second;
	uint16_t milliSecond;
};

constexpr uint8_t timestampSize = 32;
using CPFTimestamp = std::array<char, timestampSize>;

/** Get the 3-letter month name
 *
 * This function is implemented in system_time.cpp and not required to be
 * implemented by the platform.
 *
 * @param[in] month_num The numerical number corresponding to the month, where
 * 	1 = January. If 0 is supplied, "NaMonth" will be returned.
 * @returns the 3-letter name of the Month.
 */
std::string_view getMonthText(uint8_t month_num);
uint64_t getUptimeMilliseconds();
DateTimeStruct getDateTimeNow();
CPFTimestamp getTimestamp();
CPFTimestamp dateTimeToTimestamp(const DateTimeStruct& input);

constexpr uint32_t MS_PER_SEC = 1000;
constexpr uint8_t SECS_PER_MIN = 60;
constexpr uint32_t SECS_PER_HOUR = 3600;
constexpr uint8_t MINS_PER_HOUR = 60;
constexpr uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24;
// This is niave...
constexpr uint32_t SECS_PER_YEAR = SECS_PER_DAY * 365;

// Return the number of ms from start to finish. If start > finish, answer will be < 0.
int64_t getDuration_ms(const DateTimeStruct finish, const DateTimeStruct start);

int64_t secondsSince1900Epoch(const DateTimeStruct t);

/// Delay for the specified number of milliseconds
void delay(uint32_t delay_in_ms);
void delay(std::chrono::duration<uint32_t, std::milli> delay_in_ms);

/// Adjust a datetime struct with a tickstamp
/// @param [in] inTime The time to adjust
/// @param [in] adjustment_milliseconds The number of milliseconds to adjust by
systime::DateTimeStruct adjustTime(systime::DateTimeStruct inTime, std::chrono::milliseconds adjustment_milliseconds);

} // namespace systime
