#include "i2c.hpp"

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

#include <cassert>
#include <cerrno>
#include <cstring>
#include <format>

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

namespace i2c
{

// Maximum number of data bytes in a block read/block write/block process call
// in SMBus 3.0. The maximum was 32 data bytes in SMBus 2.0 and earlier.
constexpr uint8_t I2C_SMBUS3_BLOCK_MAX = 255;

unsigned long I2CDevice::getFuncs()
{
    // If functionality has not been cached
    if (cachedFuncs == NO_FUNCS)
    {
        // Get functionality from adapter
        int ret = 0, retries = 0;
        do
        {
            ret = ioctl(fd, I2C_FUNCS, &cachedFuncs);
        } while ((ret < 0) && (++retries <= maxRetries));

        if (ret < 0)
        {
            cachedFuncs = NO_FUNCS;
            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;
        case I2C_SMBUS_PROC_CALL:
            if (!(funcs & I2C_FUNC_SMBUS_PROC_CALL))
            {
                throw I2CException("Missing I2C_FUNC_SMBUS_PROC_CALL", busStr,
                                   devAddr);
            }
            break;
        case I2C_SMBUS_BLOCK_PROC_CALL:
            if (!(funcs & I2C_FUNC_SMBUS_BLOCK_PROC_CALL))
            {
                throw I2CException("Missing I2C_FUNC_SMBUS_BLOCK_PROC_CALL",
                                   busStr, devAddr);
            }
            break;
        default:
            fprintf(stderr, "Unexpected write size type: %d\n", type);
            assert(false);
    }
}

void I2CDevice::processCallSMBus(uint8_t addr, uint8_t writeSize,
                                 const uint8_t* writeData, uint8_t& readSize,
                                 uint8_t* readData)
{
    int ret = 0, retries = 0;
    uint8_t buffer[I2C_SMBUS_BLOCK_MAX];
    do
    {
        // Copy write data to buffer. Buffer is also used by SMBus function to
        // store the data read from the device.
        std::memcpy(buffer, writeData, writeSize);
        ret = i2c_smbus_block_process_call(fd, addr, writeSize, buffer);
    } while ((ret < 0) && (++retries <= maxRetries));

    if (ret < 0)
    {
        throw I2CException("Failed to execute block process call", busStr,
                           devAddr, errno);
    }

    readSize = static_cast<uint8_t>(ret);
    std::memcpy(readData, buffer, readSize);
}

void I2CDevice::processCallI2C(uint8_t addr, uint8_t writeSize,
                               const uint8_t* writeData, uint8_t& readSize,
                               uint8_t* readData)
{
    // Buffer for block write. Linux supports SMBus 3.0 max size for block
    // write. Buffer will contain register address, byte count, and data bytes.
    constexpr uint16_t writeBufferSize = I2C_SMBUS3_BLOCK_MAX + 2;
    uint8_t writeBuffer[writeBufferSize];

    // Buffer for block read. Linux supports smaller SMBus 2.0 max size for
    // block read. After ioctl() buffer will contain byte count and data bytes.
    constexpr uint16_t readBufferSize = I2C_SMBUS_BLOCK_MAX + 1;
    uint8_t readBuffer[readBufferSize];

    // i2c_msg and i2c_rdwr_ioctl_data structs required for ioctl()
    constexpr unsigned int numMessages = 2;
    struct i2c_msg messages[numMessages];
    struct i2c_rdwr_ioctl_data readWriteData;
    readWriteData.msgs = messages;
    readWriteData.nmsgs = numMessages;

    int ret = 0, retries = 0;
    do
    {
        // Initialize write buffer with reg addr, byte count, and data bytes
        writeBuffer[0] = addr;
        writeBuffer[1] = writeSize;
        std::memcpy(&(writeBuffer[2]), writeData, writeSize);

        // Initialize first i2c_msg to perform block write
        messages[0].addr = devAddr;
        messages[0].flags = 0;
        messages[0].len = writeSize + 2; // 2 == reg addr + byte count
        messages[0].buf = writeBuffer;

        // Initialize read buffer. Set first byte to number of "extra bytes"
        // that will be read in addition to data bytes. Set to 1 since only
        // extra byte is the byte count.
        readBuffer[0] = 1;

        // Initialize second i2c_msg to perform block read. Linux requires the
        // len field to be set to the buffer size.
        messages[1].addr = devAddr;
        messages[1].flags = I2C_M_RD | I2C_M_RECV_LEN;
        messages[1].len = readBufferSize;
        messages[1].buf = readBuffer;

        // Call ioctl() to send the I2C messages
        ret = ioctl(fd, I2C_RDWR, &readWriteData);
    } while ((ret != numMessages) && (++retries <= maxRetries));

    if (ret < 0)
    {
        throw I2CException("Failed to execute I2C block process call", busStr,
                           devAddr, errno);
    }
    else if (ret != numMessages)
    {
        throw I2CException(
            std::format(
                "Failed to execute I2C block process call: {} messages sent",
                ret),
            busStr, devAddr);
    }

    // Read size is in first byte; copy remaining data bytes to readData param
    readSize = readBuffer[0];
    std::memcpy(readData, &(readBuffer[1]), readSize);
}

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

    int retries = 0;
    do
    {
        fd = ::open(busStr.c_str(), O_RDWR);
    } while ((fd == -1) && (++retries <= maxRetries));

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

    retries = 0;
    int ret = 0;
    do
    {
        ret = ioctl(fd, I2C_SLAVE, devAddr);
    } while ((ret < 0) && (++retries <= maxRetries));

    if (ret < 0)
    {
        // Close device since setting slave address failed
        closeWithoutException();

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

void I2CDevice::close()
{
    checkIsOpen();

    int ret = 0, retries = 0;
    do
    {
        ret = ::close(fd);
    } while ((ret == -1) && (++retries <= maxRetries));

    if (ret == -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 = 0, retries = 0;
    do
    {
        ret = i2c_smbus_read_byte(fd);
    } while ((ret < 0) && (++retries <= maxRetries));

    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 = 0, retries = 0;
    do
    {
        ret = i2c_smbus_read_byte_data(fd, addr);
    } while ((ret < 0) && (++retries <= maxRetries));

    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 = 0, retries = 0;
    do
    {
        ret = i2c_smbus_read_word_data(fd, addr);
    } while ((ret < 0) && (++retries <= maxRetries));

    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, retries = 0;
    switch (mode)
    {
        case Mode::SMBUS:
            checkReadFuncs(I2C_SMBUS_BLOCK_DATA);
            do
            {
                ret = i2c_smbus_read_block_data(fd, addr, data);
            } while ((ret < 0) && (++retries <= maxRetries));
            break;
        case Mode::I2C:
            checkReadFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
            do
            {
                ret = i2c_smbus_read_i2c_block_data(fd, addr, size, data);
            } while ((ret < 0) && (++retries <= maxRetries));
            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);

    int ret = 0, retries = 0;
    do
    {
        ret = i2c_smbus_write_byte(fd, data);
    } while ((ret < 0) && (++retries <= maxRetries));

    if (ret < 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);

    int ret = 0, retries = 0;
    do
    {
        ret = i2c_smbus_write_byte_data(fd, addr, data);
    } while ((ret < 0) && (++retries <= maxRetries));

    if (ret < 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);

    int ret = 0, retries = 0;
    do
    {
        ret = i2c_smbus_write_word_data(fd, addr, data);
    } while ((ret < 0) && (++retries <= maxRetries));

    if (ret < 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, retries = 0;
    switch (mode)
    {
        case Mode::SMBUS:
            checkWriteFuncs(I2C_SMBUS_BLOCK_DATA);
            do
            {
                ret = i2c_smbus_write_block_data(fd, addr, size, data);
            } while ((ret < 0) && (++retries <= maxRetries));
            break;
        case Mode::I2C:
            checkWriteFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
            do
            {
                ret = i2c_smbus_write_i2c_block_data(fd, addr, size, data);
            } while ((ret < 0) && (++retries <= maxRetries));
            break;
    }

    if (ret < 0)
    {
        throw I2CException("Failed to write block data", busStr, devAddr,
                           errno);
    }
}

void I2CDevice::processCall(uint8_t addr, uint16_t writeData,
                            uint16_t& readData)
{
    checkIsOpen();
    checkWriteFuncs(I2C_SMBUS_PROC_CALL);

    int ret = 0, retries = 0;
    do
    {
        ret = i2c_smbus_process_call(fd, addr, writeData);
    } while ((ret < 0) && (++retries <= maxRetries));

    if (ret < 0)
    {
        throw I2CException("Failed to execute process call", busStr, devAddr,
                           errno);
    }

    readData = static_cast<uint16_t>(ret);
}

void I2CDevice::processCall(uint8_t addr, uint8_t writeSize,
                            const uint8_t* writeData, uint8_t& readSize,
                            uint8_t* readData)
{
    checkIsOpen();
    unsigned long funcs = getFuncs();

    if ((funcs & I2C_FUNC_SMBUS_BLOCK_PROC_CALL) &&
        (writeSize <= I2C_SMBUS_BLOCK_MAX))
    {
        // Use standard SMBus function which supports smaller SMBus 2.0 maximum
        processCallSMBus(addr, writeSize, writeData, readSize, readData);
    }
    else if (funcs & I2C_FUNC_I2C)
    {
        // Use lower level I2C ioctl which supports larger SMBus 3.0 maximum
        processCallI2C(addr, writeSize, writeData, readSize, readData);
    }
    else
    {
        throw I2CException(
            std::format(
                "Block process call unsupported: writeSize={:d}, funcs={}",
                writeSize, funcs),
            busStr, devAddr);
    }
}

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

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

} // namespace i2c
