/*
 * Author:          Patrick-Christopher Mattulat
 * Co-Author:       Claude Sonnet 4.6 (LLM)
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2020-08-14
 * Changed:         2026-06-23
 *
 * */

#include <iomanip>
#include <ls-std/time/Date.hpp>
#if defined(_WIN32) || defined(__APPLE__)
  #include <sstream> // only MSVC and Apple need this
#endif

using ls::standard::core::Class;
using ls::standard::time::Date;
using std::put_time;
using std::string;
using std::stringstream;
using std::time;

Date::Date() : Class("Date")
{
  this->timestamp = ::time(nullptr);
  this->_init();
}

Date::~Date() noexcept = default;

Date &Date::operator+(const int _value)
{
  this->_incrementByDays(_value);
  return *this;
}

Date &Date::operator-(const int _value)
{
  this->_decrementByDays(_value);
  return *this;
}

Date &Date::operator+=(const int _value)
{
  this->_incrementByDays(_value);
  return *this;
}

Date &Date::operator-=(const int _value)
{
  this->_decrementByDays(_value);
  return *this;
}

bool Date::after(const Date &_foreignDate) const
{
  return this->timestamp > _foreignDate.getTime();
}

bool Date::before(const Date &_foreignDate) const
{
  return this->timestamp < _foreignDate.getTime();
}

int Date::getDay() const
{
  return this->localTime.tm_mday;
}

int Date::getHour() const
{
  return this->localTime.tm_hour;
}

int Date::getMinute() const
{
  return this->localTime.tm_min;
}

int Date::getMonth() const
{
  return this->localTime.tm_mon + 1;
}

int Date::getSecond() const
{
  return this->localTime.tm_sec;
}

int Date::getYear() const
{
  return this->localTime.tm_year + 1900;
}

time_t Date::getTime() const
{
  return this->timestamp;
}

void Date::setTime(const time_t _timestamp)
{
  this->timestamp = _timestamp;
  this->_init();
}

string Date::toString() const
{
  stringstream _stream{};
  _stream << put_time(&this->localTime, "%Y-%m-%d %H:%M:%S");

  return _stream.str();
}

void Date::_decrementByDays(const int _value)
{
  this->timestamp -= (_value * 86400);
}

void Date::_incrementByDays(const int _value)
{
  this->timestamp += (_value * 86400);
}

void Date::_init()
{
#if defined(unix) || defined(__APPLE__)
  ::localtime_r(&this->timestamp, &this->localTime);
#endif
#ifdef _WIN32
  ::localtime_s(&this->localTime, &this->timestamp);
#endif
}
