//
// Created by Lenovo on 13.10.2021.
//

#include "Date.h"
#include <string>

int64_t JDay(int year, int month, int day);
void GDate(int64_t JD, int& y, int& m, int& d);

Date::Date(int year, int month, int day) :
  year(year), month(month), day(day) {
}

bool Date::IsLeap() {
  if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
    return true;
  return false;
}
std::string Date::ToString() const {
  std::string dates;
  dates += day < 10 ? + "0" + std::to_string(day) +
  "." : std::to_string(day) + ".";
  dates += month < 10 ? + "0" + std::to_string(month) +
  "." : std::to_string(month) + ".";
  if(year < 10)
    dates += "000" + std::to_string(year);
  else if(year < 100)
    dates +="00" + std::to_string(year);
  else if(year < 1000)
    dates +="0" + std::to_string(year);
  else
    dates +=std::to_string(year);
  return dates;
}
Date Date::DaysLater(int days) const {
    Date dat;
    int y, m, d;
    int64_t jday = JDay(year, month, day);
    GDate(jday + days, y, m, d);
    dat.day = d;
    dat.month = m;
    dat.year = y;
    return dat;
}

int Date::DaysLeft(const Date& date) const {
    int64_t jday1 = JDay(year, month, day);
    int64_t jday2 = JDay(date.year, date.month, date.day);
    return jday2 - jday1;
}



int64_t JDay(int year, int month, int day) {
    if (month <= 2) {
        year--;
        month += 12;
    };
    unsigned int64_t J;
    int A = year / 100;
    A = 2 - A + (A / 4);
    J = 1461L * int64_t(year);
    J /= 4L;
    unsigned int64_t K = 306001L * int64_t(month + 1);
    K /= 10000L;
    J += K + day + 1720995L + A;
    return J;
}

void GDate(int64_t JD, int& y, int& m, int& d) {
    unsigned int64_t A = (JD * 4L - 7468865L) / 146097L;
    A = (JD > 2299160) ? JD + 1 + A - (A / 4L) : JD;
    int64_t B = A + 1524;
    int64_t C = (B * 20L - 2442L) / 7305L;
    int64_t D = (C * 1461L) / 4L;
    int64_t E = (10000L * (B - D)) / 306001L;
    d = static_cast<int>(B - D - ((E * 306001L) / 10000L));
    m = static_cast<int>((E <= 13) ? E - 1 : E - 13);
    y = static_cast<int>(C - ((m > 2) ? 4716 : 4715));
}