#include "Configuration.hpp"
#include <spdlog/fmt/fmt.h>

using namespace vera;

namespace
{
constexpr auto DEFAULT_DEVICE_MODE = "emulated";
constexpr auto DEFAULT_DEVICE_NETWORK_ADDRESS = "192.168.0.2";
constexpr auto DEFAULT_DEVICE_NETWORK_PORT = "80";

}  // namespace

std::string GeneralConfiguration::calibrationFile() const
{
  return mSection["calibration.file"].asStringOr("calibration.csv");
}

double GeneralConfiguration::peakPosition() const
{
  return mSection["peak.position[wn]"].asDoubleOr(1084.0);
}

double GeneralConfiguration::smoothing() const
{
  return mSection["smoothing[wn]"].asDoubleOr(134.05);
}

std::string GeneralConfiguration::arduinoComPort() const
{
  return mSection["arduino.com.port"].asStringOr("COM2");
}

bool GeneralConfiguration::repeatAutomatically() const
{
  return mSection["repeat.automatically"].asBoolOr(false);
}

Duration GeneralConfiguration::repeatWait() const
{
  return Duration{mSection["repeat.wait[s]"].asDoubleOr(5.0)};
}

double GeneralConfiguration::peakSearchWidth() const
{
  return mSection["peak.search.width[wn]"].asDoubleOr(10.0);
}

double GeneralConfiguration::peakIsolation() const
{
  return mSection["peak.isolation[wn]"].asDoubleOr(20.0);
}

bool GeneralConfiguration::useBaseLine() const
{
  return mSection["use.base.line"].asBoolOr(false);
}

Configuration::Configuration(std::string filename) : mReader(filename)
{
}

std::string PumpConfiguration::mode() const
{
  return mSection["mode"].asStringOr(DEFAULT_DEVICE_MODE);
}

std::chrono::duration<double> PumpConfiguration::sampleTime() const
{
  return Duration{mSection["sample.time[s]"].asDoubleOr(1.0)};
}

Duration PumpConfiguration::evaporationTime() const
{
  return Duration{mSection["evaporation.time[s]"].asDoubleOr(3.0)};
}

Duration PumpConfiguration::loadTime() const
{
  return Duration{mSection["load.time[s]"].asDoubleOr(1.0)};
}

Duration PumpConfiguration::unloadTime() const
{
  return Duration{mSection["unload.time[s]"].asDoubleOr(1.0)};
}

HeaterConfiguration::HeaterConfiguration(schneide::ini::Section section)
: mSection(std::move(section))
{
}

std::string HeaterConfiguration::mode() const
{
  return mSection["mode"].asStringOr(DEFAULT_DEVICE_MODE);
}

std::string HeaterConfiguration::rampFile() const
{
  return mSection["ramp.file"].asStringOr("ramp.csv");
}

std::string HeaterConfiguration::COMPort() const
{
  return mSection["com.port"].asStringOr("COM1");
}

int HeaterConfiguration::TDKAddress() const
{
  return mSection["tdk.address"].asIntegerOr(1);
}

Duration HeaterConfiguration::preHeatTime() const
{
  return Duration{mSection["pre.heat.time[s]"].asDoubleOr(0.0)};
}

std::string vera::HeaterConfiguration::networkAddress() const
{
  return mSection["network.address"].asStringOr(DEFAULT_DEVICE_NETWORK_ADDRESS);
}

std::string vera::HeaterConfiguration::networkPort() const
{
  return mSection["network.port"].asStringOr(DEFAULT_DEVICE_NETWORK_PORT);
}

std::string PositionerConfiguration::mode() const
{
  return mSection["mode"].asStringOr(DEFAULT_DEVICE_MODE);
}

int PositionerConfiguration::measurementPosition() const
{
  return mSection["measurement.position[deg]"].asIntegerOr(30);
}

int PositionerConfiguration::loadingPosition() const
{
  return mSection["loading.position[deg]"].asIntegerOr(90);
}

std::chrono::duration<double> PositionerConfiguration::waitTime() const
{
  return std::chrono::duration<double>{
    mSection["wait.time[s]"].asDoubleOr(1.0)};
}

HeaterConfiguration Configuration::heater() const
{
  return HeaterConfiguration{mReader["Heater"]};
}

FTIRConfiguration Configuration::ftir() const
{
  return FTIRConfiguration{mReader["FTIR"]};
}

GeneralConfiguration Configuration::general() const
{
  return GeneralConfiguration{mReader["General"]};
}

PositionerConfiguration Configuration::positioner() const
{
  return PositionerConfiguration(mReader["Positioner"]);
}

PumpConfiguration Configuration::pump() const
{
  return PumpConfiguration(mReader["Pump"]);
}
