#include "IpmbSDRSensor.hpp"

#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>

#include <cmath>
#include <cstddef>
#include <cstdint>
#include <functional>
#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)
    {
        lg2::error("Error reading from IPMB SDR for host '{INDEX}'", "INDEX",
                   hostIndex);
        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)
            {
                lg2::error(
                    "IPMB Get SDR Repository Info data is empty for host '{INDEX}'",
                    "INDEX", self->hostIndex);
                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)
            {
                lg2::error(
                    "IPMB SDR Reserve Repository data is empty for host '{INDEX}'",
                    "INDEX", self->hostIndex);
                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)
            {
                lg2::error("IPMB SDR sensor data is empty for host '{INDEX}'",
                           "INDEX", self->hostIndex);
                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;
}
