#include "IpmbSDRSensor.hpp"

#include <sdbusplus/asio/connection.hpp>

#include <cmath>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <vector>

const constexpr char* ipmbService = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
const constexpr char* ipmbDbusPath = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
const constexpr char* ipmbInterface = "org.openbmc.Ipmb";
const constexpr char* ipmbMethod = "sendRequest";
static constexpr uint8_t lun = 0;

IpmbSDRDevice::IpmbSDRDevice(
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
    uint8_t cmdAddr) :
    commandAddress(cmdAddr << 2),
    hostIndex(cmdAddr + 1), conn(dbusConnection)
{}

bool validateStatus(boost::system::error_code ec,
                    const IpmbMethodType& response, int hostIndex)
{
    if (ec)
    {
        return false;
    }

    const int status = std::get<0>(response);
    if (status != 0)
    {
        std::cerr << "Error reading from IPMB SDR for host " << hostIndex
                  << "\n";
        return false;
    }
    return true;
}

/* This function will store the record count of the SDR sensors for each IPMB
 * bus */
void IpmbSDRDevice::getSDRRepositoryInfo()
{
    std::weak_ptr<IpmbSDRDevice> weakRef = weak_from_this();

    conn->async_method_call(
        [weakRef](boost::system::error_code ec,
                  const IpmbMethodType& response) {
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }

        auto status = std::bind_front(validateStatus, ec, response);
        if (!status(self->hostIndex))
        {
            return;
        }

        const std::vector<uint8_t>& data = std::get<5>(response);
        const size_t sdrInfoDataSize = 14;

        if (data.size() < sdrInfoDataSize)
        {
            std::cerr << " IPMB Get SDR Repository Info data is empty for host "
                      << self->hostIndex << "\n";
            return;
        }

        constexpr uint8_t recordCountLSB = 1;
        constexpr uint8_t recordCountMSB = 2;

        uint16_t recordCount = (data[recordCountMSB] << 8) |
                               data[recordCountLSB];

        self->reserveSDRRepository(recordCount);
    },
        ipmbService, ipmbDbusPath, ipmbInterface, ipmbMethod, commandAddress,
        sdr::netfnStorageReq, lun, sdr::cmdStorageGetSdrInfo, sdrCommandData);
}

/* This function will store the reserve ID for each IPMB bus index */
void IpmbSDRDevice::reserveSDRRepository(uint16_t recordCount)
{
    std::weak_ptr<IpmbSDRDevice> weakRef = weak_from_this();

    conn->async_method_call(
        [weakRef, recordCount](boost::system::error_code ec,
                               const IpmbMethodType& response) {
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }

        auto status = std::bind_front(validateStatus, ec, response);
        if (!status(self->hostIndex))
        {
            return;
        }

        const std::vector<uint8_t>& data = std::get<5>(response);
        const size_t sdrReserveDataSize = 2;

        if (data.size() < sdrReserveDataSize)
        {
            std::cerr << " IPMB SDR Reserve Repository data is empty for host "
                      << self->hostIndex << "\n";
            return;
        }
        uint8_t resrvIDLSB = data[0];
        uint8_t resrvIDMSB = data[1];

        self->getSDRSensorData(recordCount, resrvIDLSB, resrvIDMSB);
    },
        ipmbService, ipmbDbusPath, ipmbInterface, ipmbMethod, commandAddress,
        sdr::netfnStorageReq, lun, sdr::cmdStorageReserveSdr, sdrCommandData);
}

/* This function will read all the information related to the sensor
 * such as name, threshold value, unit, device address, SDR type */
void IpmbSDRDevice::getSDRSensorData(uint16_t recordCount, uint8_t resrvIDLSB,
                                     uint8_t resrvIDMSB)
{
    std::weak_ptr<IpmbSDRDevice> weakRef = weak_from_this();

    uint8_t loopCount = sdr::perCountByte * iCnt;
    std::vector<uint8_t> commandData = {resrvIDLSB,      resrvIDMSB,
                                        nextRecordIDLSB, nextRecordIDMSB,
                                        loopCount,       sdr::perCountByte};

    conn->async_method_call(
        [weakRef, recordCount, resrvIDLSB, resrvIDMSB](
            boost::system::error_code ec, const IpmbMethodType& response) {
        auto self = weakRef.lock();
        if (!self)
        {
            return;
        }

        auto status = std::bind_front(validateStatus, ec, response);
        if (!status(self->hostIndex))
        {
            return;
        }

        const std::vector<uint8_t>& data = std::get<5>(response);
        const size_t sdrSensorDataSize = 18;

        if (data.size() < sdrSensorDataSize)
        {
            std::cerr << "IPMB SDR sensor data is empty for host "
                      << self->hostIndex << "\n";
            return;
        }

        self->handleSDRData(data, recordCount, resrvIDLSB, resrvIDMSB);
    },
        ipmbService, ipmbDbusPath, ipmbInterface, ipmbMethod, commandAddress,
        sdr::netfnStorageReq, lun, sdr::cmdStorageGetSdr, commandData);
}

/* This function will handle the sensor data received by IPMB response */
void IpmbSDRDevice::handleSDRData(const std::vector<uint8_t>& data,
                                  uint16_t recordCount, uint8_t resrvIDLSB,
                                  uint8_t resrvIDMSB)
{
    sdrData.insert(sdrData.end(), data.begin(), data.end());

    /* dataLength represents the size of data for SDR types */
    uint8_t dataLength = sdrData[sdr::dataLengthByte] + sdr::dataLengthByte + 1;

    /*  If sdrData size is less than dataLength, it will call getSDRSensorData
     *  function recursively till all the data is received.
     */
    if (sdrData.size() < dataLength)
    {
        iCnt++;
        getSDRSensorData(recordCount, resrvIDLSB, resrvIDMSB);
    }
    else
    {
        /*  After all the data is received, it is passed to checkSDRData
         *  function. Next sensor record ID is stored based on the previous
         *  record ID. Vector of sdrData is cleared to store next sensor data.
         *  validRecordCount is incremented and getSDRSensorData function is
         *  called to proceed with next set of sensors.
         */
        checkSDRData(sdrData, dataLength);
        iCnt = 0;
        nextRecordIDLSB = sdrData[sdr::sdrNxtRecLSB];
        nextRecordIDMSB = sdrData[sdr::sdrNxtRecMSB];
        sdrData.clear();

        if (validRecordCount == recordCount)
        {
            /* Once all the sensors are read and recordCount matched, it will
             * return. */
            nextRecordIDLSB = 0;
            nextRecordIDMSB = 0;
            return;
        }
        validRecordCount++;
        getSDRSensorData(recordCount, resrvIDLSB, resrvIDMSB);
    }
}

/* This function will convert the SDR sensor data such as sensor unit, name, ID,
 * type from decimal to readable format */
void IpmbSDRDevice::checkSDRData(std::vector<uint8_t>& sdrDataBytes,
                                 uint8_t dataLength) const
{
    if (sdrDataBytes.size() < dataLength)
    {
        return;
    }

    /* sdrType represents the SDR Type (Byte 5) such as 1, 2, 3 */
    uint8_t sdrType = sdrDataBytes[sdr::sdrType];
    if (sdrType != static_cast<uint8_t>(SDRType::sdrType01))
    {
        return;
    }

    /*  dataLen represents the data length (Byte 6) for SDR sensor */
    int dataLen = sdrDataBytes[sdr::dataLengthByte];

    /* iStrLen represents the length of the sensor name for SDR Type 1 */
    const uint8_t sdrLenBit = 0x1F;
    int strLen = (sdrDataBytes[sdrtype01::nameLengthByte]) & (sdrLenBit);

    /* iStrAddr represents the starting byte (Byte 56) for SDR sensor name */
    int strAddr = dataLen + ((dataLen / (sdr::perCountByte)) * 4) -
                  (strLen - 1);

    /* Below for loop will convert the bytes to string and form a sensor name */

    std::string tempName(sdrDataBytes.begin() + strAddr,
                         sdrDataBytes.begin() + strAddr + strLen);

    checkSDRType01Threshold(sdrDataBytes, (hostIndex - 1), tempName);
}

/* This function will convert the raw value of threshold for each sensor */
void IpmbSDRDevice::checkSDRType01Threshold(std::vector<uint8_t>& sdrDataBytes,
                                            int busIndex, std::string tempName)
{
    const uint8_t bitShiftMsb = 2;
    const uint8_t sdrThresAccess = 0x0C;

    /* linear represents the sensor's linearization (Byte 27) */
    uint8_t linear = sdrDataBytes[sdrtype01::sdrLinearByte];
    if (linear != 0)
    {
        return;
    }

    /* sdrSensCapability (Byte 13) and(&) with sdrThresAccess(0x0C) will declare
     * whether threshold is present for each sensor */
    int threshold = (sdrDataBytes[sdrtype01::sensorCapability]) &
                    (sdrThresAccess);

    /* mData        - 10 bits
     * mDataByte    - Byte 28 - 8 bits LSB
     * mTolDataByte - Byte 29 - 2 bits MSB [7-6]
     */
    uint16_t mData = ((sdrDataBytes[sdrtype01::mTolDataByte] & 0xC0)
                      << bitShiftMsb) |
                     sdrDataBytes[sdrtype01::mDataByte];

    /* bData        - 10 bits
     * bDataByte    - Byte 30 - 8 bits LSB
     * bAcuDataByte - Byte 31 - 2 bits MSB [7-6]
     */
    uint16_t bData = ((sdrDataBytes[sdrtype01::bAcuDataByte] & 0xC0)
                      << bitShiftMsb) |
                     sdrDataBytes[sdrtype01::bDataByte];

    /* rbExpDataByte (Byte 33) represents the exponent value
     *  Bit [3-0] - B Exponent 2's complement signed bit.
     *  Bit [7-4] - R Exponent 2's complement signed bit.
     */
    int8_t bExpVal = sdrDataBytes[sdrtype01::rbExpDataByte] & 0xF;
    if (bExpVal > 7)
    {
        bExpVal = (~bExpVal + 1) & 0xF;
    }

    /* Shifting the data to right by 4, since rExpVal has 4 bits from 4 to 7 in
     * byte 33 */
    int8_t rExpVal = (sdrDataBytes[sdrtype01::rbExpDataByte] >> 4) & 0xF;
    if (rExpVal > 7)
    {
        rExpVal = (~rExpVal + 1) & 0xF;
        rExpVal = -rExpVal;
    }

    /* Sensor Threshold Reading Conversion
     *
     *  Y = ((Mx + (B * 10^K1)) * (10^K2))
     *
     *  X  - Raw value of threshold
     *  M  - mData Value
     *  B  - bData Value
     *  K1 - Signed Exponent of bExpVal
     *  K2 - Signed Exponent of rExpVal
     */

    double bDataVal = bData * pow(10, bExpVal);
    double expVal = pow(10, rExpVal);

    double thresUpCri =
        sensorValCalculation(mData, bDataVal, expVal,
                             sdrDataBytes[sdrtype01::upperCriticalThreshold]);
    double thresLoCri =
        sensorValCalculation(mData, bDataVal, expVal,
                             sdrDataBytes[sdrtype01::lowerCriticalThreshold]);

    struct SensorInfo temp;

    temp.sensorReadName = std::move(tempName);
    temp.sensorUnit = sdrDataBytes[sdrtype01::sdrUnitType];

    temp.thresUpperCri = thresUpCri;
    temp.thresLowerCri = thresLoCri;

    temp.sensorNumber = sdrDataBytes[sdr::sdrSensorNum];
    temp.sensCap = threshold;

    sensorRecord[busIndex].emplace_back(std::move(temp));

    SensorValConversion val = {mData, bDataVal, expVal,
                               sdrDataBytes[sdrtype01::sdrNegHandle]};

    sensorValRecord[busIndex][sdrDataBytes[sdr::sdrSensorNum]] = val;
}

/* This function will calculate the sensor's threshold value */
double IpmbSDRDevice::sensorValCalculation(uint16_t mValue, double bValue,
                                           double expValue, double value)
{
    double sensorValue = ((mValue * value) + bValue) * expValue;
    return sensorValue;
}
