/**
 * Copyright © 2019 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "extended_user_header.hpp"

#include "json_utils.hpp"
#include "pel_types.hpp"
#include "pel_values.hpp"

#include <fmt/format.h>

#include <phosphor-logging/log.hpp>

namespace openpower
{
namespace pels
{

namespace pv = openpower::pels::pel_values;
using namespace phosphor::logging;
const size_t defaultSymptomIDWord = 3;
const size_t symptomIDMaxSize = 80;

ExtendedUserHeader::ExtendedUserHeader(Stream& pel)
{
    try
    {
        unflatten(pel);
        validate();
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            fmt::format("Cannot unflatten extended user header: {}", e.what())
                .c_str());
        _valid = false;
    }
}

ExtendedUserHeader::ExtendedUserHeader(const DataInterfaceBase& dataIface,
                                       const message::Entry& regEntry,
                                       const SRC& src) :
    _mtms(dataIface.getMachineTypeModel(), dataIface.getMachineSerialNumber())
{
    _header.id = static_cast<uint16_t>(SectionID::extendedUserHeader);
    _header.version = extendedUserHeaderVersion;
    _header.subType = 0;
    _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);

    memset(_serverFWVersion.data(), 0, _serverFWVersion.size());
    auto version = dataIface.getServerFWVersion();

    // The last byte must always be the NULL terminator
    for (size_t i = 0; i < version.size() && i < firmwareVersionSize - 1; i++)
    {
        _serverFWVersion[i] = version[i];
    }

    memset(_subsystemFWVersion.data(), 0, _subsystemFWVersion.size());
    version = dataIface.getBMCFWVersion();

    // The last byte must always be the NULL terminator
    for (size_t i = 0; i < version.size() && i < firmwareVersionSize - 1; i++)
    {
        _subsystemFWVersion[i] = version[i];
    }

    createSymptomID(regEntry, src);

    _header.size = flattenedSize();
    _valid = true;
}

void ExtendedUserHeader::flatten(Stream& pel) const
{
    pel << _header << _mtms;
    pel.write(_serverFWVersion.data(), _serverFWVersion.size());
    pel.write(_subsystemFWVersion.data(), _subsystemFWVersion.size());
    pel << _reserved4B << _refTime << _reserved1B1 << _reserved1B2
        << _reserved1B3 << _symptomIDSize << _symptomID;
}

void ExtendedUserHeader::unflatten(Stream& pel)
{
    pel >> _header >> _mtms;
    pel.read(_serverFWVersion.data(), _serverFWVersion.size());
    pel.read(_subsystemFWVersion.data(), _subsystemFWVersion.size());
    pel >> _reserved4B >> _refTime >> _reserved1B1 >> _reserved1B2 >>
        _reserved1B3 >> _symptomIDSize;

    _symptomID.resize(_symptomIDSize);
    pel >> _symptomID;
}

void ExtendedUserHeader::validate()
{
    bool failed = false;

    if (header().id != static_cast<uint16_t>(SectionID::extendedUserHeader))
    {
        log<level::ERR>(
            fmt::format("Invalid ExtendedUserHeader section ID: {0:#x}",
                        header().id)
                .c_str());
        failed = true;
    }

    if (header().version != extendedUserHeaderVersion)
    {
        log<level::ERR>(
            fmt::format("Invalid ExtendedUserHeader version: {0:#x}",
                        header().version)
                .c_str());
        failed = true;
    }

    _valid = (failed) ? false : true;
}

void ExtendedUserHeader::createSymptomID(const message::Entry& regEntry,
                                         const SRC& src)
{
    // Contains the first 8 characters of the ASCII string plus additional
    // words from the SRC, separated by underscores.  The message registry
    // says which words to use, though that's optional and if not present
    // then use a default word.
    std::vector<size_t> idWords;

    if (regEntry.src.symptomID)
    {
        idWords = regEntry.src.symptomID.value();
    }
    else
    {
        idWords.push_back(defaultSymptomIDWord);
    }

    auto symptomID = src.asciiString().substr(0, 8);

    const auto& hexWords = src.hexwordData();

    for (auto wordNum : idWords)
    {
        symptomID.push_back('_');

        // Get the hexword array index for this SRC word
        auto index = src.getWordIndexFromWordNum(wordNum);

        // Convert to ASCII
        char word[20];
        sprintf(word, "%08X", hexWords[index]);
        symptomID += word;
    }

    std::copy(symptomID.begin(), symptomID.end(),
              std::back_inserter(_symptomID));

    // Max total size is 80, including the upcoming NULL
    if (_symptomID.size() > (symptomIDMaxSize - 1))
    {
        _symptomID.resize(symptomIDMaxSize - 1);
    }

    // NULL terminated
    _symptomID.push_back(0);

    // PAD with NULLs to a 4 byte boundary
    while ((_symptomID.size() % 4) != 0)
    {
        _symptomID.push_back(0);
    }

    _symptomIDSize = _symptomID.size();
}

std::optional<std::string> ExtendedUserHeader::getJSON(uint8_t creatorID) const
{
    std::string json;
    jsonInsert(json, pv::sectionVer, getNumberString("%d", _header.version), 1);
    jsonInsert(json, pv::subSection, getNumberString("%d", _header.subType), 1);
    jsonInsert(json, pv::createdBy,
               getComponentName(_header.componentID, creatorID), 1);
    jsonInsert(json, "Reporting Machine Type", machineTypeModel(), 1);
    jsonInsert(json, "Reporting Serial Number", trimEnd(machineSerialNumber()),
               1);
    jsonInsert(json, "FW Released Ver", serverFWVersion(), 1);
    jsonInsert(json, "FW SubSys Version", subsystemFWVersion(), 1);
    jsonInsert(json, "Common Ref Time",
               getNumberString("%02X", _refTime.month) + '/' +
                   getNumberString("%02X", _refTime.day) + '/' +
                   getNumberString("%02X", _refTime.yearMSB) +
                   getNumberString("%02X", _refTime.yearLSB) + ' ' +
                   getNumberString("%02X", _refTime.hour) + ':' +
                   getNumberString("%02X", _refTime.minutes) + ':' +
                   getNumberString("%02X", _refTime.seconds),
               1);
    jsonInsert(json, "Symptom Id Len", getNumberString("%d", _symptomIDSize),
               1);
    jsonInsert(json, "Symptom Id", symptomID(), 1);
    json.erase(json.size() - 2);
    return json;
}

} // namespace pels
} // namespace openpower
