
#include "io.hpp"
#include "logger.h"
#include "pins.hpp"
#include "WiFi.h"
#include "driver/adc.h"
#include <esp_wifi.h>
#include <esp_bt.h>

extern logging::Logger logger;


IO::IO() : oneWire(DI_DALLAS), sensors(&oneWire) {
    // Constructor body (if needed)
}

#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 600

void IO::setup_io()
{
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "SETUP IO");
  oneWire.begin(DI_DALLAS);
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "oneWire.begin");
  sensors.begin();
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "sensors.begi");
  sensors.setResolution(12);
}

void IO::set_low_power()
{
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "Set lower power attrs");

  pinMode(DI_LED, OUTPUT);
  digitalWrite(DI_LED, LOW); // TODO check if pin 22(ledbuiltin 2) is a led
  setCpuFrequencyMhz(80);
  WiFi.mode(WIFI_OFF);
  btStop();
  esp_wifi_stop();
  esp_bt_controller_disable();
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  adc_power_on();
}

void IO::set_deep_sleep()
{
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "Going to sleep");
  esp_deep_sleep_start();
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "Will not reach");
}

uint8_t IO::read_battery()
{
  uint8_t percentage = 100;

  float voltage = analogRead(ADC_BATTERY) / 4096.0 * 7.46;
  // float voltage = analogRead(35) / 4096.0 * 7.46;
  if (voltage > 1)
  { // Only display if there is a valid reading
    percentage = 2836.9625 * pow(voltage, 4) - 43987.4889 * pow(voltage, 3) + 255233.8134 * pow(voltage, 2) - 656689.7123 * voltage + 632041.7303;
    if (voltage >= 4.20)
      percentage = 100;
    if (voltage <= 3.50)
      percentage = 0;
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Voltage: %f", voltage);
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Percentage: %d", percentage);
  }

  return percentage;
}

float IO::read_temp()
{
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "IO", "read_temp");
  sensors.requestTemperatures(); // Request temperature readings
  delay(1000);
  float tempC = sensors.getTempCByIndex(0);
  if (tempC != DEVICE_DISCONNECTED_C)
  {
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Temp: %f", tempC);
  }
  else if(tempC == -127.00) {
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Couldn't read temp");
  }
  else
  {
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "Couldn't read temp");
  }
   return tempC;
}

float IO::read_internal_temp()
{
  float chipTemp = temperatureRead();
  logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "io", "chipTemp: %f", chipTemp);
  return chipTemp;
}