#include "ipmi_fru_info_area.hpp"

#include <phosphor-logging/elog.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 manufacturingDateSize = 0x3;
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)
        {
            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);
        }

        // 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 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(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
