#include "keyword_vpd_parser.hpp"

#include "const.hpp"

#include <iostream>
#include <numeric>
#include <string>

using namespace openpower::vpd::constants;
using namespace openpower::vpd::inventory;
using namespace std;
using namespace openpower::vpd;

namespace vpd
{
namespace keyword
{
namespace parser
{

variant<KeywordVpdMap, store> KeywordVpdParser::parse()
{
    int kwVpdType;

    validateLargeResourceIdentifierString();

    kwVpdType = validateTheTypeOfKwVpd();

    auto kwValMap = kwValParser();

    // Do not process these two functions for bono type VPD
    if (!kwVpdType)
    {
        validateSmallResourceTypeEnd();

        validateChecksum();
    }

    validateSmallResourceTypeLastEnd();

#ifdef DEBUG_KW_VPD
    cerr << '\n' << " KW " << '\t' << "  VALUE " << '\n';
    for (const auto& it : kwValMap)
    {
        cerr << '\n' << " " << it->first << '\t';
        copy((it->second).begin(), (it->second).end(),
             ostream_iterator<int>(cout << hex, " "));
    }
#endif

    return kwValMap;
}

void KeywordVpdParser::validateLargeResourceIdentifierString()
{
    kwVpdIterator = keywordVpdVector.begin();

    // Check for large resource type identifier string
    if (*kwVpdIterator != KW_VPD_START_TAG)
    {
        throw std::runtime_error(
            "Invalid Large resource type Identifier String");
    }

    itrOutOfBoundCheck(1);
    advance(kwVpdIterator, sizeof(KW_VPD_START_TAG));
}

int KeywordVpdParser::validateTheTypeOfKwVpd()
{
    size_t dataSize = getKwDataSize();

    itrOutOfBoundCheck(TWO_BYTES + dataSize);

#ifdef DEBUG_KW_VPD
    auto dsDeb = dataSize;
    auto itDeb = kwVpdIterator + TWO_BYTES;
    std::cout << '\n' << '\t';
    while (dsDeb != 0)
    {
        std::cout << *itDeb;
        itDeb++;
        dsDeb--;
    }
    std::cout << '\n';
#endif

    // +TWO_BYTES is the description's size byte
    std::advance(kwVpdIterator, TWO_BYTES + dataSize);

    int kwVpdType = 0;
    // Check for invalid vendor defined large resource type
    if (*kwVpdIterator != KW_VAL_PAIR_START_TAG)
    {
        if (*kwVpdIterator != ALT_KW_VAL_PAIR_START_TAG)
        {
            throw std::runtime_error("Invalid Keyword Value Pair Start Tag");
        }
        // Bono vpd referred as 1
        kwVpdType = 1;
    }
    return kwVpdType;
}

KeywordVpdMap KeywordVpdParser::kwValParser()
{
    int totalSize = 0;
    KeywordVpdMap kwValMap;

    checkSumStart = kwVpdIterator;

    itrOutOfBoundCheck(1);
    kwVpdIterator++;

    // Get the total length of all keyword value pairs
    totalSize = getKwDataSize();

    if (totalSize == 0)
    {
        throw std::runtime_error("Badly formed keyword VPD data");
    }

    itrOutOfBoundCheck(TWO_BYTES);
    std::advance(kwVpdIterator, TWO_BYTES);

    // Parse the keyword-value and store the pairs in map
    while (totalSize > 0)
    {
        std::string kwStr(kwVpdIterator, kwVpdIterator + TWO_BYTES);

        totalSize -= TWO_BYTES;
        itrOutOfBoundCheck(TWO_BYTES);
        std::advance(kwVpdIterator, TWO_BYTES);

        size_t kwSize = *kwVpdIterator;

        itrOutOfBoundCheck(1);
        kwVpdIterator++;

        std::vector<uint8_t> valVec(kwVpdIterator, kwVpdIterator + kwSize);

        itrOutOfBoundCheck(kwSize);
        std::advance(kwVpdIterator, kwSize);

        totalSize -= kwSize + 1;

        kwValMap.emplace(std::make_pair(std::move(kwStr), std::move(valVec)));
    }

    checkSumEnd = kwVpdIterator - 1;

    return kwValMap;
}

void KeywordVpdParser::validateSmallResourceTypeEnd()
{
    // Check for small resource type end tag
    if (*kwVpdIterator != KW_VAL_PAIR_END_TAG)
    {
        throw std::runtime_error("Invalid Small resource type End");
    }
}

void KeywordVpdParser::validateChecksum()
{
    uint8_t checkSum = 0;

    // Checksum calculation
    checkSum = std::accumulate(checkSumStart, checkSumEnd + 1, checkSum);
    checkSum = ~checkSum + 1;

    if (checkSum != *(kwVpdIterator + 1))
    {
        throw std::runtime_error("Invalid Check sum");
    }
#ifdef DEBUG_KW_VPD
    std::cout << "\nCHECKSUM : " << std::hex << static_cast<int>(checkSum)
              << std::endl;
#endif

    itrOutOfBoundCheck(TWO_BYTES);
    std::advance(kwVpdIterator, TWO_BYTES);
}

void KeywordVpdParser::validateSmallResourceTypeLastEnd()
{
    // Check for small resource type last end of data
    if (*kwVpdIterator != KW_VPD_END_TAG)
    {
        throw std::runtime_error(
            "Invalid Small resource type Last End Of Data");
    }
}

size_t KeywordVpdParser::getKwDataSize()
{
    return (*(kwVpdIterator + 1) << 8 | *kwVpdIterator);
}

void KeywordVpdParser::itrOutOfBoundCheck(uint8_t incVar)
{
    if ((std::distance(keywordVpdVector.begin(), kwVpdIterator + incVar)) >
        std::distance(keywordVpdVector.begin(), keywordVpdVector.end()))
    {
        throw std::runtime_error("Badly formed VPD data");
    }
}

std::string KeywordVpdParser::getInterfaceName() const
{
    return kwdVpdInf;
}

} // namespace parser
} // namespace keyword
} // namespace vpd
