#define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG

#include <DebugLog.h>
#include <DebugLogEnable.h>
#include <Arduino.h>
#include <RS485_Driver.h>
#include <TCA9554PWR_Driver.h>
#include <PCF85063_Driver.h>
#include <ETH_Driver.h>

#include "utils.h"

/////////////// GLOBALS ///////////////
void setup()
{
  Serial.begin(9600);
  LOG_ATTACH_SERIAL(Serial);
}

void loop()
{
  const uint8_t tempBoardAddr(0xAA);
  const uint8_t relayBoardAddr(0x01);
  const uint8_t baseRegister(0x00);

  //////////////// DEVICES ////////////////
  // Declared here to keep devices local to the main loop otherwise the kernel crashes //
  auto i2c = drivers::I2C();
  auto relays = drivers::TCA9554PWR(i2c, TCA9554_ADDRESS);
  auto bus = drivers::MODBUS(9600, SERIAL_8N1);
  auto rtc = drivers::PCF85063(i2c, PCF85063_ADDRESS);
  auto eth = drivers::Ethernet("waveshare-test");

  Network.onEvent([&eth](arduino_event_id_t event, arduino_event_info_t info)
                  { eth.onEvent(event, info); });

  while (!eth.isConnected())
  {
    LOG_WARN("Waiting for Ethernet");
    delay(1000);
  }
  
  // Set RTC time at startup
  time_t ntpTime;
  drivers::PCF85063::datetime_t dt;
  eth.getNtpTime(ntpTime);
  rtc.setDatetime(drivers::PCF85063::fromEpoch(ntpTime));

  ////////////////////////////////////////
  ///////// MAIN LOOP INSIDE LOOP ////////
  ////////////////////////////////////////

  while (true)
  {
    LOG_INFO("[", k++, "] Loop");
    std::vector<uint16_t> results;
    std::vector<bool> values;

    eth.getNtpTime(ntpTime);
    dt = drivers::PCF85063::fromEpoch(ntpTime);
    LOG_INFO("Netwrok Datetime", rtc.datetime2str(dt).c_str());
    LOG_INFO("Current Datetime", rtc.getTimeStr().c_str());

    if (bus.readHoldingRegisters(tempBoardAddr, baseRegister, 8, results))
    {
      for (auto i(0); i < results.size(); i++)
      {
        LOG_INFO("[", i, "]Temperature: ", results.at(i) / 10.0f);
      }
      results.clear();
    }

    delay(100);
    LOG_INFO("\n\n====>Read Inputs");
    bus.readInputs(relayBoardAddr, 0x00, 8, values);
    printBool("====>Inputs", values);

    delay(5000);
  }

  ////////////////////////////////////////
  ///////// MAIN LOOP INSIDE LOOP ////////
  ////////////////////////////////////////
}