/*
 * MIT License
 * Copyright (c) 2018 Brian T. Park
 */

#include <Arduino.h>
#include <AceCommon.h> // printPad2To()
#include "common/DateStrings.h" // DateStrings
#include "LocalDate.h"

namespace ace_time {

// Offsets used to calculate the day of the week of a particular (year, month,
// day). The element represents the number of days that the first of month of
// the given index was shifted by the cummulative days from the previous months.
// To determine the "day of the week", we must normalize the resulting "day of
// the week" modulo 7.
//
// January is index 0, but we also use a modified year, where the year starts in
// March to make leap years easier to handle, so the shift for March=3 is 0.
//
// For example:
//    * atc_days_of_week[3] is 3 because April (index=3) 1st is shifted by 3
//      days because March has 31 days (28 + 3).
//    * atc_days_of_week[4] is 5 because May (index=4) 1st is shifted by 2
//      additional days from April, because April has 30 days (28 + 2).
const uint8_t LocalDate::sDayOfWeek[12] = {
  5 /*Jan=31*/,
  1 /*Feb=28*/,
  0 /*Mar=31, start of "year"*/,
  3 /*Apr=30*/,
  5 /*May=31*/,
  1 /*Jun=30*/,
  3 /*Jul=31*/,
  6 /*Aug=31*/,
  2 /*Sep=30*/,
  4 /*Oct=31*/,
  0 /*Nov=30*/,
  2 /*Dec=31*/,
};

// Using 0=Jan offset.
const uint8_t LocalDate::sDaysInMonth[12] = {
  31 /*Jan=31*/,
  28 /*Feb=28*/,
  31 /*Mar=31*/,
  30 /*Apr=30*/,
  31 /*May=31*/,
  30 /*Jun=30*/,
  31 /*Jul=31*/,
  31 /*Aug=31*/,
  30 /*Sep=30*/,
  31 /*Oct=31*/,
  30 /*Nov=30*/,
  31 /*Dec=31*/,
};

void LocalDate::printTo(Print& printer) const {
  if (isError()) {
    printer.print(F("<Invalid LocalDate>"));
    return;
  }

  // Date
  using ace_common::printPad2To;
  printer.print(year());
  printer.print('-');
  printPad2To(printer, mMonth, '0');
  printer.print('-');
  printPad2To(printer, mDay, '0');
  printer.print(' ');

  // Week day
  DateStrings ds;
  printer.print(ds.dayOfWeekLongString(dayOfWeek()));
}

}
