/**
 * 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 "pel_utils.hpp"

#include "extensions/openpower-pels/private_header.hpp"
#include "extensions/openpower-pels/user_header.hpp"

#include <fstream>

#include <gtest/gtest.h>

namespace fs = std::filesystem;
using namespace openpower::pels;

std::filesystem::path CleanLogID::pelIDFile{};
std::filesystem::path CleanPELFiles::pelIDFile{};
std::filesystem::path CleanPELFiles::repoPath{};
std::filesystem::path CleanPELFiles::registryPath{};

const std::vector<uint8_t> privateHeaderSection{
    // section header
    0x50, 0x48, // ID 'PH'
    0x00, 0x30, // Size
    0x01, 0x02, // version, subtype
    0x03, 0x04, // comp ID

    0x20, 0x30, 0x05, 0x09, 0x11, 0x1E, 0x1,  0x63, // create timestamp
    0x20, 0x31, 0x06, 0x0F, 0x09, 0x22, 0x3A, 0x00, // commit timestamp
    0x4F,                                           // creatorID 'O'
    0x00,                                           // logtype
    0x00,                                           // reserved
    0x02,                                           // section count
    0x90, 0x91, 0x92, 0x93,                         // OpenBMC log ID
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0,    // creator version
    0x50, 0x51, 0x52, 0x53,                         // plid
    0x80, 0x81, 0x82, 0x83};                        // PEL ID

const std::vector<uint8_t> userHeaderSection{
    // section header
    0x55, 0x48, // ID 'UH'
    0x00, 0x18, // Size
    0x01, 0x0A, // version, subtype
    0x0B, 0x0C, // comp ID

    0x10, 0x04,             // subsystem, scope
    0x20, 0x00,             // severity, type
    0x00, 0x00, 0x00, 0x00, // reserved
    0x03, 0x04,             // problem domain, vector
    0x80, 0xC0,             // action flags
    0x00, 0x00, 0x00, 0x00  // reserved
};

const std::vector<uint8_t> srcSectionNoCallouts{

    // Header
    'P', 'S', 0x00, 0x50, 0x01, 0x01, 0x02, 0x02,

    0x02, 0x00, 0x00, // version, flags, reserved
    0x09, 0x00, 0x00, // hex word count, reserved2B
    0x00, 0x48,       // SRC structure size

    // Hex words 2 - 9
    0x02, 0x02, 0x02, 0x55, 0x03, 0x03, 0x03, 0x10, 0x04, 0x04, 0x04, 0x04,
    0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
    0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
    // ASCII string
    'B', 'D', '8', 'D', '5', '6', '7', '8', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
    ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
    ' ', ' '};

const std::vector<uint8_t> failingMTMSSection{
    // Header
    0x4D, 0x54, 0x00, 0x1C, 0x01, 0x00, 0x20, 0x00,

    'T',  'T',  'T',  'T',  '-',  'M',  'M',  'M',  '1', '2',
    '3',  '4',  '5',  '6',  '7',  '8',  '9',  'A',  'B', 'C'};

const std::vector<uint8_t> UserDataSection{
    // Header
    0x55, 0x44, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00,

    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

const std::vector<uint8_t> ExtUserHeaderSection{
    // Header
    'E', 'H', 0x00, 0x60, 0x01, 0x00, 0x03, 0x04,

    // MTMS
    'T', 'T', 'T', 'T', '-', 'M', 'M', 'M', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', 'A', 'B', 'C',

    // Server FW version
    'S', 'E', 'R', 'V', 'E', 'R', '_', 'V', 'E', 'R', 'S', 'I', 'O', 'N', '\0',
    '\0',

    // Subsystem FW Version
    'B', 'M', 'C', '_', 'V', 'E', 'R', 'S', 'I', 'O', 'N', '\0', '\0', '\0',
    '\0', '\0',

    0x00, 0x00, 0x00, 0x00,                         // Reserved
    0x20, 0x25, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, // Ref time
    0x00, 0x00, 0x00,                               // Reserved

    // SymptomID length and symptom ID
    20, 'B', 'D', '8', 'D', '4', '2', '0', '0', '_', '1', '2', '3', '4', '5',
    '6', '7', '8', '\0', '\0', '\0'};

const std::vector<uint8_t> srcFRUIdentityCallout{
    'I', 'D', 0x1C, 0x1D,                     // type, size, flags
    '1', '2', '3',  '4',                      // PN
    '5', '6', '7',  0x00, 'A', 'A', 'A', 'A', // CCIN
    '1', '2', '3',  '4',  '5', '6', '7', '8', // SN
    '9', 'A', 'B',  'C'};

const std::vector<uint8_t> srcPCEIdentityCallout{
    'P', 'E', 0x24, 0x00,                      // type, size, flags
    'T', 'T', 'T',  'T',  '-', 'M', 'M',  'M', // MTM
    '1', '2', '3',  '4',  '5', '6', '7',       // SN
    '8', '9', 'A',  'B',  'C', 'P', 'C',  'E', // Name + null padded
    'N', 'A', 'M',  'E',  '1', '2', 0x00, 0x00, 0x00};

const std::vector<uint8_t> srcMRUCallout{
    'M',  'R',  0x28, 0x04, // ID, size, flags
    0x00, 0x00, 0x00, 0x00, // Reserved
    0x00, 0x00, 0x00, 'H',  // priority 0
    0x01, 0x01, 0x01, 0x01, // MRU ID 0
    0x00, 0x00, 0x00, 'M',  // priority 1
    0x02, 0x02, 0x02, 0x02, // MRU ID 1
    0x00, 0x00, 0x00, 'L',  // priority 2
    0x03, 0x03, 0x03, 0x03, // MRU ID 2
    0x00, 0x00, 0x00, 'H',  // priority 3
    0x04, 0x04, 0x04, 0x04, // MRU ID 3
};

const std::vector<uint8_t> extendedUserDataSection{
    // Header
    0x45, 0x44, 0x00, 0x18, 0x01, 0x02, 0x20, 0x00,

    // Creator ID 'O', and then data
    0x4F, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    0x05, 0x0A, 0x0B, 0x0C};

constexpr size_t sectionCountOffset = 27;
constexpr size_t createTimestampPHOffset = 8;
constexpr size_t commitTimestampPHOffset = 16;
constexpr size_t creatorPHOffset = 24;
constexpr size_t obmcIDPHOffset = 28;
constexpr size_t plidPHOffset = 40;
constexpr size_t pelIDPHOffset = 44;
constexpr size_t sevUHOffset = 10;
constexpr size_t actionFlagsUHOffset = 18;

std::vector<uint8_t> pelDataFactory(TestPELType type)
{
    std::vector<uint8_t> data;

    switch (type)
    {
        case TestPELType::pelSimple:
            data.insert(data.end(), privateHeaderSection.begin(),
                        privateHeaderSection.end());
            data.insert(data.end(), userHeaderSection.begin(),
                        userHeaderSection.end());
            data.insert(data.end(), srcSectionNoCallouts.begin(),
                        srcSectionNoCallouts.end());
            data.insert(data.end(), failingMTMSSection.begin(),
                        failingMTMSSection.end());
            data.insert(data.end(), UserDataSection.begin(),
                        UserDataSection.end());
            data.insert(data.end(), ExtUserHeaderSection.begin(),
                        ExtUserHeaderSection.end());
            data.insert(data.end(), extendedUserDataSection.begin(),
                        extendedUserDataSection.end());
            data.at(sectionCountOffset) = 7;
            break;
        case TestPELType::privateHeaderSection:
            data.insert(data.end(), privateHeaderSection.begin(),
                        privateHeaderSection.end());
            break;
        case TestPELType::userHeaderSection:
            data.insert(data.end(), userHeaderSection.begin(),
                        userHeaderSection.end());
            break;
        case TestPELType::primarySRCSection:
            data.insert(data.end(), srcSectionNoCallouts.begin(),
                        srcSectionNoCallouts.end());
            break;
        case TestPELType::primarySRCSection2Callouts:
        {
            // Start with the no-callouts SRC, and add the callouts section
            // from above.
            auto src = srcSectionNoCallouts;
            auto callouts =
                srcDataFactory(TestSRCType::calloutSection2Callouts);

            src.insert(src.end(), callouts.begin(), callouts.end());

            // Set the flag that says there are callouts
            // One byte after the 8B header
            src[8 + 1] |= 0x01;

            // Set the new sizes
            uint16_t size = src.size();
            Stream stream{src};

            stream.offset(2); // In the header
            stream << size;

            // In the SRC - the size field doesn't include the header
            size -= 8;
            stream.offset(8 + 6);
            stream << size;

            data.insert(data.end(), src.begin(), src.end());
            break;
        }
        case TestPELType::failingMTMSSection:
            data.insert(data.end(), failingMTMSSection.begin(),
                        failingMTMSSection.end());
        case TestPELType::extendedUserDataSection:
            data.insert(data.end(), extendedUserDataSection.begin(),
                        extendedUserDataSection.end());
    }
    return data;
}

std::vector<uint8_t> pelFactory(uint32_t id, char creatorID, uint8_t severity,
                                uint16_t actionFlags, size_t size)
{
    std::vector<uint8_t> data;
    size_t offset = 0;

    auto now = std::chrono::system_clock::now();
    auto timestamp = getBCDTime(now);

    // Start with the default Private Header, and modify it
    data.insert(data.end(), privateHeaderSection.begin(),
                privateHeaderSection.end());
    data.at(creatorPHOffset) = creatorID;

    // Modify the multibyte fields in it
    Stream stream{data};
    stream.offset(createTimestampPHOffset);
    stream << timestamp;
    stream.offset(commitTimestampPHOffset);
    stream << timestamp;
    stream.offset(plidPHOffset);
    stream << id;
    stream.offset(pelIDPHOffset);
    stream << id;
    stream.offset(obmcIDPHOffset);
    stream << id + 500;

    offset = data.size();

    // User Header
    data.insert(data.end(), userHeaderSection.begin(), userHeaderSection.end());
    data.at(offset + sevUHOffset) = severity;
    data.at(offset + actionFlagsUHOffset) = actionFlags >> 8;
    data.at(offset + actionFlagsUHOffset + 1) = actionFlags;

    // Use the default SRC, failing MTMS, and ext user Header sections
    auto src = pelDataFactory(TestPELType::primarySRCSection2Callouts);

    data.insert(data.end(), src.begin(), src.end());
    data.insert(data.end(), failingMTMSSection.begin(),
                failingMTMSSection.end());
    data.insert(data.end(), ExtUserHeaderSection.begin(),
                ExtUserHeaderSection.end());

    data.at(sectionCountOffset) = 5;

    // Require the size to be enough for all the above sections.
    assert(size >= data.size());
    assert(size <= 16384);

    // Add a UserData section to get the size we need.
    auto udSection = UserDataSection;
    udSection.resize(size - data.size());

    if (!udSection.empty())
    {
        // At least has to be 8B for the header
        assert(udSection.size() >= 8);

        // UD sections must be 4B aligned
        assert(udSection.size() % 4 == 0);

        // Set the new size in the section heder
        Stream udStream{udSection};
        udStream.offset(2);
        udStream << static_cast<uint16_t>(udSection.size());

        data.insert(data.end(), udSection.begin(), udSection.end());
        data[sectionCountOffset]++;
    }

    assert(size == data.size());
    return data;
}

std::vector<uint8_t> srcDataFactory(TestSRCType type)
{
    switch (type)
    {
        case TestSRCType::fruIdentityStructure:
            return srcFRUIdentityCallout;

        case TestSRCType::pceIdentityStructure:
            return srcPCEIdentityCallout;

        case TestSRCType::mruStructure:
            return srcMRUCallout;

        case TestSRCType::calloutStructureA:
        {
            // Add just the FRU identity substructure to the base structure
            std::vector<uint8_t> data{
                0xFF, 0x28, 'H', 4,   // size, flags, priority, LC length
                'U',  '4',  '2', 0x00 // LC
            };

            data.insert(data.end(), srcFRUIdentityCallout.begin(),
                        srcFRUIdentityCallout.end());

            // The final size
            data[0] = data.size();
            return data;
        }
        case TestSRCType::calloutStructureB:
        {
            // Add all 3 substructures to the base structure

            std::vector<uint8_t> data{
                0xFF, 0x2F, 'L', 8, // size, flags, priority, LC length
                'U',  '1',  '2', '-', 'P', '1', 0x00, 0x00 // LC
            };
            data.insert(data.end(), srcFRUIdentityCallout.begin(),
                        srcFRUIdentityCallout.end());
            data.insert(data.end(), srcPCEIdentityCallout.begin(),
                        srcPCEIdentityCallout.end());
            data.insert(data.end(), srcMRUCallout.begin(), srcMRUCallout.end());

            // The final size
            data[0] = data.size();
            return data;
        }
        case TestSRCType::calloutSection2Callouts:
        {
            std::vector<uint8_t> data{0xC0, 0x00, 0x00,
                                      0x00}; // ID, flags, length in words

            // Add 2 callouts
            auto callout = srcDataFactory(TestSRCType::calloutStructureA);
            data.insert(data.end(), callout.begin(), callout.end());

            callout = srcDataFactory(TestSRCType::calloutStructureB);
            data.insert(data.end(), callout.begin(), callout.end());

            // Set the actual word length value at offset 2
            Stream stream{data};
            uint16_t wordLength = data.size() / 4;
            stream.offset(2);
            stream << wordLength;
            stream.offset(0);

            return data;
        }
    }
    return {};
}

std::unique_ptr<std::vector<uint8_t>> readPELFile(const fs::path& path)
{
    std::ifstream file{path};

    auto pel = std::make_unique<std::vector<uint8_t>>(
        std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
    return pel;
}
