#include "ipmi_fru_info_area.hpp"

#include <algorithm>
#include <ctime>
#include <iomanip>
#include <map>
#include <numeric>
#include <phosphor-logging/elog.hpp>
#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 model = "Model";
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 manufacturingDateSize = 0x3;
static constexpr auto areaSizeOffset = 0x1;
static constexpr uint8_t typeASCII = 0xC0;
static constexpr auto maxRecordAttributeValue = 0x1F;

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 (std::exception& e)
        {
            log<level::ERR>("Could not parse chassis type",
                            entry("VALUE=%s", value.c_str()),
                            entry("ERROR=%s", e.what()));
            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);
        }

        // 5 bits for length
        // if length is greater then 31(2^5) bytes then trim the data to 31
        // 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 std::mktime(&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(model, 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(model, 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 = std::move(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 = std::move(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 = std::move(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
