#include "i2c.hpp"

#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>

#include <cassert>
#include <cerrno>

extern "C"
{
#include <i2c/smbus.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
}

namespace i2c
{

unsigned long I2CDevice::getFuncs()
{
    // If functionality has not been cached
    if (cachedFuncs == NO_FUNCS)
    {
        // Get functionality from adapter
        if (ioctl(fd, I2C_FUNCS, &cachedFuncs) < 0)
        {
            throw I2CException("Failed to get funcs", busStr, devAddr, errno);
        }
    }

    return cachedFuncs;
}

void I2CDevice::checkReadFuncs(int type)
{
    unsigned long funcs = getFuncs();
    switch (type)
    {
        case I2C_SMBUS_BYTE:
            if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE))
            {
                throw I2CException("Missing SMBUS_READ_BYTE", busStr, devAddr);
            }
            break;
        case I2C_SMBUS_BYTE_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
            {
                throw I2CException("Missing SMBUS_READ_BYTE_DATA", busStr,
                                   devAddr);
            }
            break;

        case I2C_SMBUS_WORD_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA))
            {
                throw I2CException("Missing SMBUS_READ_WORD_DATA", busStr,
                                   devAddr);
            }
            break;
        case I2C_SMBUS_BLOCK_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA))
            {
                throw I2CException("Missing SMBUS_READ_BLOCK_DATA", busStr,
                                   devAddr);
            }
            break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK))
            {
                throw I2CException("Missing I2C_FUNC_SMBUS_READ_I2C_BLOCK",
                                   busStr, devAddr);
            }
            break;
        default:
            fprintf(stderr, "Unexpected read size type: %d\n", type);
            assert(false);
            break;
    }
}

void I2CDevice::checkWriteFuncs(int type)
{
    unsigned long funcs = getFuncs();
    switch (type)
    {
        case I2C_SMBUS_BYTE:
            if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
            {
                throw I2CException("Missing SMBUS_WRITE_BYTE", busStr, devAddr);
            }
            break;
        case I2C_SMBUS_BYTE_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
            {
                throw I2CException("Missing SMBUS_WRITE_BYTE_DATA", busStr,
                                   devAddr);
            }
            break;

        case I2C_SMBUS_WORD_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA))
            {
                throw I2CException("Missing SMBUS_WRITE_WORD_DATA", busStr,
                                   devAddr);
            }
            break;
        case I2C_SMBUS_BLOCK_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
            {
                throw I2CException("Missing SMBUS_WRITE_BLOCK_DATA", busStr,
                                   devAddr);
            }
            break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
            if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
            {
                throw I2CException("Missing I2C_FUNC_SMBUS_WRITE_I2C_BLOCK",
                                   busStr, devAddr);
            }
            break;
        default:
            fprintf(stderr, "Unexpected read size type: %d\n", type);
            assert(false);
    }
}

void I2CDevice::open()
{
    if (isOpen())
    {
        throw I2CException("Device already open", busStr, devAddr);
    }

    fd = ::open(busStr.c_str(), O_RDWR);
    if (fd == -1)
    {
        throw I2CException("Failed to open", busStr, devAddr, errno);
    }

    if (ioctl(fd, I2C_SLAVE, devAddr) < 0)
    {
        // Close device since setting slave address failed
        closeWithoutException();

        throw I2CException("Failed to set I2C_SLAVE", busStr, devAddr, errno);
    }
}

void I2CDevice::close()
{
    checkIsOpen();
    if (::close(fd) == -1)
    {
        throw I2CException("Failed to close", busStr, devAddr, errno);
    }
    fd = INVALID_FD;
    cachedFuncs = NO_FUNCS;
}

void I2CDevice::read(uint8_t& data)
{
    checkIsOpen();
    checkReadFuncs(I2C_SMBUS_BYTE);

    int ret = i2c_smbus_read_byte(fd);
    if (ret < 0)
    {
        throw I2CException("Failed to read byte", busStr, devAddr, errno);
    }
    data = static_cast<uint8_t>(ret);
}

void I2CDevice::read(uint8_t addr, uint8_t& data)
{
    checkIsOpen();
    checkReadFuncs(I2C_SMBUS_BYTE_DATA);

    int ret = i2c_smbus_read_byte_data(fd, addr);
    if (ret < 0)
    {
        throw I2CException("Failed to read byte data", busStr, devAddr, errno);
    }
    data = static_cast<uint8_t>(ret);
}

void I2CDevice::read(uint8_t addr, uint16_t& data)
{
    checkIsOpen();
    checkReadFuncs(I2C_SMBUS_WORD_DATA);
    int ret = i2c_smbus_read_word_data(fd, addr);
    if (ret < 0)
    {
        throw I2CException("Failed to read word data", busStr, devAddr, errno);
    }
    data = static_cast<uint16_t>(ret);
}

void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data, Mode mode)
{
    checkIsOpen();
    int ret = -1;
    switch (mode)
    {
        case Mode::SMBUS:
            checkReadFuncs(I2C_SMBUS_BLOCK_DATA);
            ret = i2c_smbus_read_block_data(fd, addr, data);
            break;
        case Mode::I2C:
            checkReadFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
            ret = i2c_smbus_read_i2c_block_data(fd, addr, size, data);
            if (ret != size)
            {
                throw I2CException("Failed to read i2c block data", busStr,
                                   devAddr, errno);
            }
            break;
    }
    if (ret < 0)
    {
        throw I2CException("Failed to read block data", busStr, devAddr, errno);
    }
    size = static_cast<uint8_t>(ret);
}

void I2CDevice::write(uint8_t data)
{
    checkIsOpen();
    checkWriteFuncs(I2C_SMBUS_BYTE);

    if (i2c_smbus_write_byte(fd, data) < 0)
    {
        throw I2CException("Failed to write byte", busStr, devAddr, errno);
    }
}

void I2CDevice::write(uint8_t addr, uint8_t data)
{
    checkIsOpen();
    checkWriteFuncs(I2C_SMBUS_BYTE_DATA);

    if (i2c_smbus_write_byte_data(fd, addr, data) < 0)
    {
        throw I2CException("Failed to write byte data", busStr, devAddr, errno);
    }
}

void I2CDevice::write(uint8_t addr, uint16_t data)
{
    checkIsOpen();
    checkWriteFuncs(I2C_SMBUS_WORD_DATA);

    if (i2c_smbus_write_word_data(fd, addr, data) < 0)
    {
        throw I2CException("Failed to write word data", busStr, devAddr, errno);
    }
}

void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data,
                      Mode mode)
{
    checkIsOpen();
    int ret = -1;
    switch (mode)
    {
        case Mode::SMBUS:
            checkWriteFuncs(I2C_SMBUS_BLOCK_DATA);
            ret = i2c_smbus_write_block_data(fd, addr, size, data);
            break;
        case Mode::I2C:
            checkWriteFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
            ret = i2c_smbus_write_i2c_block_data(fd, addr, size, data);
            break;
    }
    if (ret < 0)
    {
        throw I2CException("Failed to write block data", busStr, devAddr,
                           errno);
    }
}

std::unique_ptr<I2CInterface> I2CDevice::create(uint8_t busId, uint8_t devAddr,
                                                InitialState initialState)
{
    std::unique_ptr<I2CDevice> dev(new I2CDevice(busId, devAddr, initialState));
    return dev;
}

std::unique_ptr<I2CInterface> create(uint8_t busId, uint8_t devAddr,
                                     I2CInterface::InitialState initialState)
{
    return I2CDevice::create(busId, devAddr, initialState);
}

} // namespace i2c
