#include "tdklambda.hpp"

#include <iostream>
#include <asio.hpp>
#include <spdlog/spdlog.h>

#include <spdlog/sinks/stdout_color_sinks.h>
#include <random>

void run();

using tcp = asio::ip::tcp;

std::shared_ptr<spdlog::logger> const& logger()
{
  static std::shared_ptr<spdlog::logger> logger;
  if (!logger)
    logger = spdlog::stdout_color_mt("console");
  return logger;
}


class peer
{
public:
  peer()
    : m_port(m_io_service, "/dev/tty.usbserial")
  {
    logger()->info("Open? {0}", m_port.is_open());
    m_port.set_option(asio::serial_port::baud_rate(9600));
    m_port.set_option(asio::serial_port::parity(asio::serial_port::parity::none));
    m_port.set_option(asio::serial_port::stop_bits(asio::serial_port::stop_bits::one));
  }

  void send(std::string const& message)
  {
    asio::write(m_port, asio::buffer(message));
  }

  std::string receive()
  {
    std::string result;
    tcp::endpoint sender_endpoint;

    auto length = asio::read_until(m_port, asio::dynamic_buffer(result), "\r");

    return result;
  }

  std::string query(std::string message)
  {

    logger()->info("Sending \"{0}\"", message);
    message += "\r";
    send(message);
    auto response = receive();
    for (auto& each : response)
    {
      if (each == '\r')
        each = ' ';
    }
    logger()->info("Response \"{0}\"", response);
    return response;
  }

private:
  asio::io_service m_io_service;
  asio::serial_port m_port;
};

void run()
{
  peer p;
  p.query("ADR 6"); // Address the device
  p.query("IDN?");
  p.query("PV?");
  p.query("PC?");
  p.query("OUT 1"); // Enable output
  p.query("OUT?");
  p.query("PV 42"); // Set voltage
  p.query("DVC?"); // Read Measured Voltage, Programmed Voltage, Measured Current, Programmed Current, Over Voltage Set point and Under Voltage Set Point
}
