#include "ipmi_fru_info_area.hpp"

#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.hpp>

#include <algorithm>
#include <ctime>
#include <iomanip>
#include <map>
#include <numeric>
#include <sstream>

namespace ipmi
{
namespace fru
{
using namespace phosphor::logging;

// Property variables
static constexpr auto partNumber = "Part Number";
static constexpr auto serialNumber = "Serial Number";
static constexpr auto manufacturer = "Manufacturer";
static constexpr auto buildDate = "Mfg Date";
static constexpr auto modelNumber = "Model Number";
static constexpr auto prettyName = "Name";
static constexpr auto version = "Version";
static constexpr auto type = "Type";

// Board info areas
static constexpr auto board = "Board";
static constexpr auto chassis = "Chassis";
static constexpr auto product = "Product";

static constexpr auto specVersion = 0x1;
static constexpr auto recordUnitOfMeasurement = 0x8; // size in bytes
static constexpr auto checksumSize = 0x1;            // size in bytes
static constexpr auto recordNotPresent = 0x0;
static constexpr auto englishLanguageCode = 0x0;
static constexpr auto typeLengthByteNull = 0x0;
static constexpr auto endOfCustomFields = 0xC1;
static constexpr auto commonHeaderFormatSize = 0x8; // size in bytes
static constexpr auto areaSizeOffset = 0x1;
static constexpr uint8_t typeASCII = 0xC0;
static constexpr auto maxRecordAttributeValue = 0x3F;

static constexpr auto secs_from_1970_1996 = 820454400;
static constexpr auto maxMfgDateValue = 0xFFFFFF; // 3 Byte length
static constexpr auto secs_per_min = 60;
static constexpr auto secsToMaxMfgdate =
    secs_from_1970_1996 + secs_per_min * maxMfgDateValue;

// Minimum size of resulting FRU blob.
// This is also the theoretical maximum size according to the spec:
// 8 bytes header + 5 areas at 0xff*8 bytes max each
// 8 + 5*0xff*8 = 0x27e0
static constexpr auto fruMinSize = 0x27E0;

// Value to use for padding.
// Using 0xff to match the default (blank) value in a physical EEPROM.
static constexpr auto fruPadValue = 0xff;

/**
 * @brief Format Beginning of Individual IPMI FRU Data Section
 *
 * @param[in] langCode Language code
 * @param[in/out] data FRU area data
 */
void preFormatProcessing(bool langCode, FruAreaData& data)
{
    // Add id for version of FRU Info Storage Spec used
    data.emplace_back(specVersion);

    // Add Data Size - 0 as a placeholder, can edit after the data is finalized
    data.emplace_back(typeLengthByteNull);

    if (langCode)
    {
        data.emplace_back(englishLanguageCode);
    }
}

/**
 * @brief Append checksum of the FRU area data
 *
 * @param[in/out] data FRU area data
 */
void appendDataChecksum(FruAreaData& data)
{
    uint8_t checksumVal = std::accumulate(data.begin(), data.end(), 0);
    // Push the Zero checksum as the last byte of this data
    // This appears to be a simple summation of all the bytes
    data.emplace_back(-checksumVal);
}

/**
 * @brief Append padding bytes for the FRU area data
 *
 * @param[in/out] data FRU area data
 */
void padData(FruAreaData& data)
{
    uint8_t pad = (data.size() + checksumSize) % recordUnitOfMeasurement;
    if (pad)
    {
        data.resize((data.size() + recordUnitOfMeasurement - pad));
    }
}

/**
 * @brief Format End of Individual IPMI FRU Data Section
 *
 * @param[in/out] fruAreaData FRU area info data
 */
void postFormatProcessing(FruAreaData& data)
{
    // This area needs to be padded to a multiple of 8 bytes (after checksum)
    padData(data);

    // Set size of data info area
    data.at(areaSizeOffset) =
        (data.size() + checksumSize) / (recordUnitOfMeasurement);

    // Finally add area checksum
    appendDataChecksum(data);
}

/**
 * @brief Read chassis type property value from inventory and append to the FRU
 * area data.
 *
 * @param[in] propMap map of property values
 * @param[in,out] data FRU area data to be appended
 */
void appendChassisType(const PropertyMap& propMap, FruAreaData& data)
{
    uint8_t chassisType = 0; // Not specified
    auto iter = propMap.find(type);
    if (iter != propMap.end())
    {
        auto value = iter->second;
        try
        {
            chassisType = std::stoi(value);
        }
        catch (const std::exception& e)
        {
            lg2::error("Could not parse chassis type, value: {VALUE}, "
                       "error: {ERROR}",
                       "VALUE", value, "ERROR", e);
            chassisType = 0;
        }
    }
    data.emplace_back(chassisType);
}

/**
 * @brief Read property value from inventory and append to the FRU area data
 *
 * @param[in] key key to search for in the property inventory data
 * @param[in] propMap map of property values
 * @param[in,out] data FRU area data to be appended
 */
void appendData(const Property& key, const PropertyMap& propMap,
                FruAreaData& data)
{
    auto iter = propMap.find(key);
    if (iter != propMap.end())
    {
        auto value = iter->second;
        // If starts with 0x or 0X remove them
        // ex: 0x123a just take 123a
        if ((value.compare(0, 2, "0x")) == 0 ||
            (value.compare(0, 2, "0X") == 0))
        {
            value.erase(0, 2);
        }

        // 6 bits for length as per FRU spec v1.0
        // if length is greater then 63(2^6) bytes then trim the data to 63
        // bytess.
        auto valueLength = (value.length() > maxRecordAttributeValue)
                               ? maxRecordAttributeValue
                               : value.length();
        // 2 bits for type
        // Set the type to ascii
        uint8_t typeLength = valueLength | ipmi::fru::typeASCII;

        data.emplace_back(typeLength);
        std::copy(value.begin(), value.begin() + valueLength,
                  std::back_inserter(data));
    }
    else
    {
        // set 0 size
        data.emplace_back(typeLengthByteNull);
    }
}

std::time_t timeStringToRaw(const std::string& input)
{
    // TODO: For non-US region timestamps, pass in region information for the
    // FRU to avoid the month/day swap.
    // 2017-02-24 - 13:59:00, Tue Nov 20 23:08:00 2018
    static const std::vector<std::string> patterns = {"%Y-%m-%d - %H:%M:%S",
                                                      "%a %b %d %H:%M:%S %Y"};

    std::tm time = {};

    for (const auto& pattern : patterns)
    {
        std::istringstream timeStream(input);
        timeStream >> std::get_time(&time, pattern.c_str());
        if (!timeStream.fail())
        {
            break;
        }
    }

    return timegm(&time);
}

/**
 * @brief Appends Build Date
 *
 * @param[in] propMap map of property values
 * @param[in/out] data FRU area to add the manfufacture date
 */
void appendMfgDate(const PropertyMap& propMap, FruAreaData& data)
{
    // MFG Date/Time
    auto iter = propMap.find(buildDate);
    if ((iter != propMap.end()) && (iter->second.size() > 0))
    {
        std::time_t raw = timeStringToRaw(iter->second);

        // From FRU Spec:
        // "Mfg. Date / Time
        // Number of minutes from 0:00 hrs 1/1/96.
        // LSbyte first (little endian)
        // 00_00_00h = unspecified."
        if ((raw >= secs_from_1970_1996) && (raw <= secsToMaxMfgdate))
        {
            raw -= secs_from_1970_1996;
            raw /= secs_per_min;
            uint8_t fru_raw[3];
            fru_raw[0] = raw & 0xFF;
            fru_raw[1] = (raw >> 8) & 0xFF;
            fru_raw[2] = (raw >> 16) & 0xFF;
            std::copy(fru_raw, fru_raw + 3, std::back_inserter(data));
            return;
        }
        std::fprintf(stderr, "MgfDate invalid date: %u secs since UNIX epoch\n",
                     static_cast<unsigned int>(raw));
    }
    // Blank date
    data.emplace_back(0);
    data.emplace_back(0);
    data.emplace_back(0);
}

/**
 * @brief Builds a section of the common header
 *
 * @param[in] infoAreaSize size of the FRU area to write
 * @param[in] offset Current offset for data in overall record
 * @param[in/out] data Common Header section data container
 */
void buildCommonHeaderSection(const uint32_t& infoAreaSize, uint16_t& offset,
                              FruAreaData& data)
{
    // Check if data for internal use section populated
    if (infoAreaSize == 0)
    {
        // Indicate record not present
        data.emplace_back(recordNotPresent);
    }
    else
    {
        // offset should be multiple of 8.
        auto remainder = offset % recordUnitOfMeasurement;
        // add the padding bytes in the offset so that offset
        // will be multiple of 8 byte.
        offset += (remainder > 0) ? recordUnitOfMeasurement - remainder : 0;
        // Place data to define offset to area data section
        data.emplace_back(offset / recordUnitOfMeasurement);

        offset += infoAreaSize;
    }
}

/**
 * @brief Builds the Chassis info area data section
 *
 * @param[in] propMap map of properties for chassis info area
 * @return FruAreaData container with chassis info area
 */
FruAreaData buildChassisInfoArea(const PropertyMap& propMap)
{
    FruAreaData fruAreaData;
    if (!propMap.empty())
    {
        // Set formatting data that goes at the beginning of the record
        preFormatProcessing(false, fruAreaData);

        // chassis type
        appendChassisType(propMap, fruAreaData);

        // Chasiss part number, in config.yaml it is configured as model
        appendData(modelNumber, propMap, fruAreaData);

        // Board serial number
        appendData(serialNumber, propMap, fruAreaData);

        // Indicate End of Custom Fields
        fruAreaData.emplace_back(endOfCustomFields);

        // Complete record data formatting
        postFormatProcessing(fruAreaData);
    }
    return fruAreaData;
}

/**
 * @brief Builds the Board info area data section
 *
 * @param[in] propMap map of properties for board info area
 * @return FruAreaData container with board info area
 */
FruAreaData buildBoardInfoArea(const PropertyMap& propMap)
{
    FruAreaData fruAreaData;
    if (!propMap.empty())
    {
        preFormatProcessing(true, fruAreaData);

        // Manufacturing date
        appendMfgDate(propMap, fruAreaData);

        // manufacturer
        appendData(manufacturer, propMap, fruAreaData);

        // Product name/Pretty name
        appendData(prettyName, propMap, fruAreaData);

        // Board serial number
        appendData(serialNumber, propMap, fruAreaData);

        // Board part number
        appendData(partNumber, propMap, fruAreaData);

        // FRU File ID - Empty
        fruAreaData.emplace_back(typeLengthByteNull);

        // Empty FRU File ID bytes
        fruAreaData.emplace_back(recordNotPresent);

        // End of custom fields
        fruAreaData.emplace_back(endOfCustomFields);

        postFormatProcessing(fruAreaData);
    }
    return fruAreaData;
}

/**
 * @brief Builds the Product info area data section
 *
 * @param[in] propMap map of FRU properties for Board info area
 * @return FruAreaData container with product info area data
 */
FruAreaData buildProductInfoArea(const PropertyMap& propMap)
{
    FruAreaData fruAreaData;
    if (!propMap.empty())
    {
        // Set formatting data that goes at the beginning of the record
        preFormatProcessing(true, fruAreaData);

        // manufacturer
        appendData(manufacturer, propMap, fruAreaData);

        // Product name/Pretty name
        appendData(prettyName, propMap, fruAreaData);

        // Product part/model number
        appendData(modelNumber, propMap, fruAreaData);

        // Product version
        appendData(version, propMap, fruAreaData);

        // Serial Number
        appendData(serialNumber, propMap, fruAreaData);

        // Add Asset Tag
        fruAreaData.emplace_back(recordNotPresent);

        // FRU File ID - Empty
        fruAreaData.emplace_back(typeLengthByteNull);

        // Empty FRU File ID bytes
        fruAreaData.emplace_back(recordNotPresent);

        // End of custom fields
        fruAreaData.emplace_back(endOfCustomFields);

        postFormatProcessing(fruAreaData);
    }
    return fruAreaData;
}

FruAreaData buildFruAreaData(const FruInventoryData& inventory)
{
    FruAreaData combFruArea{};
    // Now build common header with data for this FRU Inv Record
    // Use this variable to increment size of header as we go along to determine
    // offset for the subsequent area offsets
    uint16_t curDataOffset = commonHeaderFormatSize;
    // First byte is id for version of FRU Info Storage Spec used
    combFruArea.emplace_back(specVersion);

    // 2nd byte is offset to internal use data
    combFruArea.emplace_back(recordNotPresent);

    // 3rd byte is offset to chassis data
    FruAreaData chassisArea;
    auto chassisIt = inventory.find(chassis);
    if (chassisIt != inventory.end())
    {
        chassisArea = buildChassisInfoArea(chassisIt->second);
    }
    // update the offset to chassis data.
    buildCommonHeaderSection(chassisArea.size(), curDataOffset, combFruArea);

    // 4th byte is offset to board data
    FruAreaData boardArea;
    auto boardIt = inventory.find(board);
    if (boardIt != inventory.end())
    {
        boardArea = buildBoardInfoArea(boardIt->second);
    }
    // update the offset to the board data.
    buildCommonHeaderSection(boardArea.size(), curDataOffset, combFruArea);

    // 5th byte is offset to product data
    FruAreaData prodArea;
    auto prodIt = inventory.find(product);
    if (prodIt != inventory.end())
    {
        prodArea = buildProductInfoArea(prodIt->second);
    }
    // update the offset to the product data.
    buildCommonHeaderSection(prodArea.size(), curDataOffset, combFruArea);

    // 6th byte is offset to multirecord data
    combFruArea.emplace_back(recordNotPresent);

    // 7th byte is PAD
    combFruArea.emplace_back(recordNotPresent);

    // 8th (Final byte of Header Format) is the checksum
    appendDataChecksum(combFruArea);

    // Combine everything into one full IPMI FRU specification Record
    // add chassis use area data
    combFruArea.insert(combFruArea.end(), chassisArea.begin(),
                       chassisArea.end());

    // add board area data
    combFruArea.insert(combFruArea.end(), boardArea.begin(), boardArea.end());

    // add product use area data
    combFruArea.insert(combFruArea.end(), prodArea.begin(), prodArea.end());

    // If area is smaller than the minimum size, pad it. This enables ipmitool
    // to update the FRU blob with values longer than the original payload.
    if (combFruArea.size() < fruMinSize)
    {
        combFruArea.resize(fruMinSize, fruPadValue);
    }

    return combFruArea;
}

} // namespace fru
} // namespace ipmi
