// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "include/librtc.h"

#include <inttypes.h>
#include <stdlib.h>

#include <ddk/debug.h>
#include <ddk/driver.h>

enum months {
  JANUARY = 1,  // 31 days
  FEBRUARY,     // 28 or 29
  MARCH,        // 31
  APRIL,        // 30
  MAY,          // 31
  JUNE,         // 30
  JULY,         // 31
  AUGUST,       // 31
  SEPTEMBER,    // 30
  OCTOBER,      // 31
  NOVEMBER,     // 30
  DECEMBER      // 31
};

// Leading 0 allows using the 1-indexed month values from rtc.
static const uint64_t days_in_month[] = {
    0,
    31,  // January
    28,  // February (not leap year)
    31,  // March
    30,  // April
    31,  // May
    30,  // June
    31,  // July
    31,  // August
    30,  // September
    31,  // October
    30,  // November
    31,  // December
};

// Start with seconds from the Unix epoch to 2000/1/1T00:00:00.
static const uint64_t local_epoch = 946684800;
static const uint16_t local_epoch_year = 2000;
static const uint16_t default_year = 2019;
static const uint16_t max_year = 2099;

static bool is_leap_year(uint16_t year) {
  return ((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0);
}

uint64_t seconds_since_epoch(const fuchsia_hardware_rtc_Time* rtc) {
  // First add all of the prior years.
  uint64_t days_since_local_epoch = 0;
  for (uint16_t year = local_epoch_year; year < rtc->year; year++) {
    days_since_local_epoch += is_leap_year(year) ? 366 : 365;
  }

  // Next add all the prior complete months this year.
  for (size_t month = JANUARY; month < rtc->month; month++) {
    days_since_local_epoch += days_in_month[month];
  }
  if (rtc->month > FEBRUARY && is_leap_year(rtc->year)) {
    days_since_local_epoch++;
  }

  // Add all the prior complete days.
  days_since_local_epoch += rtc->day - 1;

  // Hours, minutes, and seconds are 0 indexed.
  uint64_t hours_since_local_epoch = (days_since_local_epoch * 24) + rtc->hours;
  uint64_t minutes_since_local_epoch = (hours_since_local_epoch * 60) + rtc->minutes;
  uint64_t seconds_since_local_epoch = (minutes_since_local_epoch * 60) + rtc->seconds;

  uint64_t rtc_seconds = local_epoch + seconds_since_local_epoch;
  return rtc_seconds;
}

void seconds_to_rtc(uint64_t seconds, fuchsia_hardware_rtc_Time* rtc) {
  // subtract local epoch offset to get to rtc time
  uint64_t epoch = seconds - local_epoch;

  rtc->seconds = epoch % 60;
  epoch /= 60;
  rtc->minutes = epoch % 60;
  epoch /= 60;
  rtc->hours = epoch % 24;
  epoch /= 24;

  for (rtc->year = local_epoch_year;; rtc->year++) {
    uint32_t days_per_year = 365;
    if (is_leap_year(rtc->year)) {
      days_per_year++;
    }

    if (epoch < days_per_year) {
      break;
    }

    epoch -= days_per_year;
  }

  for (rtc->month = 1;; rtc->month++) {
    uint32_t days_per_month = days_in_month[rtc->month];
    if ((rtc->month == FEBRUARY) && is_leap_year(rtc->year)) {
      days_per_month++;
    }

    if (epoch < days_per_month) {
      break;
    }

    epoch -= days_per_month;
  }

  // remaining epoch is a whole number of days so just make it one-indexed
  rtc->day = epoch + 1;
}

uint8_t to_bcd(uint8_t binary) { return ((binary / 10) << 4) | (binary % 10); }

uint8_t from_bcd(uint8_t bcd) { return ((bcd >> 4) * 10) + (bcd & 0xf); }

// If "clock.backstop" is set in the environment, it is parsed as seconds
// since the Unix epoch and returned. If it is un-set, or parsing fails, 0 is
// returned.
uint64_t rtc_backstop_seconds(void) {
  const char* str = getenv("clock.backstop");
  if (str == NULL) {
    return 0;
  }
  return strtoll(str, NULL, 10);
}

// TODO: eventually swap rtc_is_invalid() for the positive version.
static bool rtc_is_valid(const fuchsia_hardware_rtc_Time* rtc) {
  if (rtc->year < local_epoch_year || rtc->year > max_year)
    return false;
  if (rtc->month < JANUARY || rtc->month > DECEMBER)
    return false;
  if (rtc->day == 0)
    return false;
  switch (rtc->month) {
    case JANUARY:
    case MARCH:
    case MAY:
    case JULY:
    case AUGUST:
    case OCTOBER:
    case DECEMBER:
      if (rtc->day > 31)
        return false;
      break;
    case FEBRUARY:
      if (rtc->day > (is_leap_year(rtc->year) ? 29 : 28))
        return false;
      break;
    default:
      if (rtc->day > 30)
        return false;
      break;
  }
  if (rtc->hours > 23 || rtc->minutes > 59 || rtc->seconds > 59)
    return false;

  return true;
}

bool rtc_is_invalid(const fuchsia_hardware_rtc_Time* rtc) { return !rtc_is_valid(rtc); }

// Validate that the RTC is set to a valid time, and to a relatively
// sane one. Report the validated or reset time back via rtc.
void sanitize_rtc(void* ctx, fuchsia_hardware_rtc_Time* rtc,
                  zx_status_t (*rtc_get)(void*, fuchsia_hardware_rtc_Time*),
                  zx_status_t (*rtc_set)(void*, const fuchsia_hardware_rtc_Time*)) {
  // January 1, 2019 00:00:00
  fuchsia_hardware_rtc_Time backstop_rtc = {
      .day = 1,
      .month = JANUARY,
      .year = default_year,
      .seconds = 0,
      .minutes = 0,
      .hours = 0,
  };
  zx_status_t result = rtc_get(ctx, rtc);
  if (result != ZX_OK) {
    driver_printf(DDK_LOG_ERROR, "sanitize_rtc: could not get RTC value (%d)", result);
    return;
  };
  uint64_t backstop = rtc_backstop_seconds();
  if (rtc_is_invalid(rtc) || rtc->year < default_year || seconds_since_epoch(rtc) < backstop) {
    if (backstop > 0) {
      driver_printf(DDK_LOG_INFO, "sanitize_rtc: clock set to clock.backstop=%ld\n", backstop);
      seconds_to_rtc(backstop, &backstop_rtc);
    } else {
      driver_printf(DDK_LOG_ERROR,
                    "sanitize_rtc: clock set to constant default, set clock.backstop.\n");
    }
    result = rtc_set(ctx, &backstop_rtc);
    if (result != ZX_OK) {
      driver_printf(DDK_LOG_ERROR, "sanitize_rtc: could not set RTC value (%d)", result);
      return;
    }
    *rtc = backstop_rtc;
  }
}
