#include <electricity/logger/serialport.hpp>
#include <stdexcept>
#include <string.h>
#include <unistd.h>

void SerialPort::SetAttributes(const speed_t baudrate)
{
    cfsetospeed(&configuration, baudrate);
    cfsetispeed(&configuration, baudrate);

    configuration.c_cflag = (configuration.c_cflag & ~CSIZE) | CS8; // 8 bit chars
    configuration.c_iflag &= ~IGNBRK;
    configuration.c_lflag = 0;
    configuration.c_oflag = 0;
    configuration.c_cc[VMIN] = 0; // no blocking read
    configuration.c_cc[VTIME] = 5;

    configuration.c_iflag &= ~(IXON | IXOFF | IXANY);
    configuration.c_cflag |= (CLOCAL | CREAD);
    configuration.c_cflag &= ~(PARENB | PARODD);
    configuration.c_cflag &= ~(CSTOPB | CRTSCTS);

    if(tcsetattr(device, TCSANOW, &configuration) != 0)
    {
        throw std::runtime_error("Error setting configuration of device.");
    }
}

std::string SerialPort::ReadLine()
{
    std::string retval;
    char c;
    while(read(device, &c, 1) == 1)
    {
        retval += c;
        if(c == '\n')
            break;
    }

    return retval;
}

SerialPort::SerialPort(const int fd) : device(fd)
{
    memset(&configuration, 0, sizeof(termios));
    if(tcgetattr(fd, &configuration) != 0)
    {
        throw std::runtime_error("Error getting attributes from file descriptor.");
    }
    oldConfiguration = configuration;

    SetAttributes();
}

SerialPort::~SerialPort() { tcsetattr(device, TCSANOW, &oldConfiguration); }
