#include <string.h>

#include "flash_otp.h"
#include "model.h"
#include "mpu.h"
#include "unit_variant.h"
#include TREZOR_BOARD

#ifdef KERNEL_MODE

static uint8_t unit_variant_color = 0;
static uint8_t unit_variant_packaging = 0;
static bool unit_variant_btconly = false;
static bool unit_variant_ok = false;

static int16_t unit_variant_build_year = -1;

static void unit_variant_0x01(const uint8_t *data) {
  unit_variant_color = data[1];
  unit_variant_btconly = data[2] == 1;
  unit_variant_packaging = data[3];
  unit_variant_ok = true;
}

static int16_t unit_variant_get_build_year(void) {
  uint8_t data[FLASH_OTP_BLOCK_SIZE] = {0};

  secbool result =
      flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, data, FLASH_OTP_BLOCK_SIZE);

  if (sectrue != result || data[0] == 0xFF) {
    return -1;
  }

  /**
   * Expecting format {MODEL_IDENTIFIER}-YYMMDD
   *
   * See also
   * https://docs.trezor.io/trezor-firmware/core/misc/memory.html?highlight=otp#otp
   */

  size_t len = strnlen((char *)data, FLASH_OTP_BLOCK_SIZE);

  for (int i = 0; i < len; i++) {
    if (data[i] == '-') {
      if ((len - (i + 1)) != 6) {
        return -1;
      }
      return ((int16_t)data[i + 1] - (int16_t)'0') * 10 +
             ((int16_t)data[i + 2] - (int16_t)'0');
    }
  }
  return -1;
}

void unit_variant_init(void) {
  uint8_t data[FLASH_OTP_BLOCK_SIZE];

  secbool result = flash_otp_read(FLASH_OTP_BLOCK_DEVICE_VARIANT, 0, data,
                                  FLASH_OTP_BLOCK_SIZE);

  unit_variant_build_year = unit_variant_get_build_year();

  if (sectrue == result) {
    switch (data[0]) {
      case 0x01:
        unit_variant_0x01(data);
        break;
      default:
        break;
    }
  }
}

uint8_t unit_variant_get_color(void) { return unit_variant_color; }

uint8_t unit_variant_get_packaging(void) { return unit_variant_packaging; }

bool unit_variant_get_btconly(void) { return unit_variant_btconly; }

bool unit_variant_present(void) { return unit_variant_ok; }

bool unit_variant_is_sd_hotswap_enabled(void) {
#ifndef USE_SD_CARD
  return false;
#else
#ifdef TREZOR_MODEL_T
  // early produced TTs have a HW bug that prevents hotswapping of the SD card,
  // lets check the build data and decide based on that
  if (unit_variant_build_year <= 18) {
    return false;
  }
  return true;
#else
  return true;
#endif
#endif
}

#endif  // KERNEL_MODE
