#include "reader_test.hpp"

#include "const.hpp"
#include "reader_impl.hpp"
#include "types.hpp"

#include <fstream>
#include <nlohmann/json.hpp>
#include <tuple>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

using namespace openpower::vpd::manager::reader;
using namespace openpower::vpd::inventory;
using namespace openpower::vpd::constants;

class vpdManagerReaderTest : public ::testing::Test
{
  protected:
    nlohmann::json jsonFile;

    // map to hold the mapping of location code and inventory path
    LocationCodeMap fruLocationCode;

    // dummy value of node number
    const uint8_t nodeNumber = 1;

  public:
    // constructor
    vpdManagerReaderTest()
    {
        processJson();
    }

    void processJson();
};

using namespace openpower::vpd;

void vpdManagerReaderTest::processJson()
{
    // read the json file and parse it
    std::ifstream json("vpd-manager-test/vpd_reader_test.json",
                       std::ios::binary);

    if (!json)
    {
        throw std::runtime_error("json file not found");
    }

    jsonFile = nlohmann::json::parse(json);

    if (jsonFile.find("frus") == jsonFile.end())
    {
        throw std::runtime_error("frus group not found in json");
    }

    const nlohmann::json& groupFRUS =
        jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
    for (const auto& itemFRUS : groupFRUS.items())
    {
        const std::vector<nlohmann::json>& groupEEPROM =
            itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
        for (const auto& itemEEPROM : groupEEPROM)
        {
            fruLocationCode.emplace(
                itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
                          ["LocationCode"]
                              .get_ref<const nlohmann::json::string_t&>(),
                itemEEPROM["inventoryPath"]
                    .get_ref<const nlohmann::json::string_t&>());
        }
    }
}

TEST_F(vpdManagerReaderTest, isValidLocationCode_invalid)
{
    // No MTS or FCS in the collapsed location code
    std::string unexpandedLocationCode_Invalid = "Uabc-X0";

    MockUtilCalls uCalls;
    ReaderImpl read(uCalls);
    EXPECT_ANY_THROW({
        read.getExpandedLocationCode(unexpandedLocationCode_Invalid, nodeNumber,
                                     fruLocationCode);
    });

    // not starting with U
    unexpandedLocationCode_Invalid = "Mabc-X0";
    EXPECT_ANY_THROW({
        read.getExpandedLocationCode(unexpandedLocationCode_Invalid, nodeNumber,
                                     fruLocationCode);
    });
}

TEST_F(vpdManagerReaderTest, getExpandedLocationCode_Invalid)
{
    std::string unexpandedLocationCode_Invalid = "Uabc-X0";

    MockUtilCalls uCalls;
    ReaderImpl read(uCalls);
    EXPECT_ANY_THROW({
        read.getExpandedLocationCode(unexpandedLocationCode_Invalid, nodeNumber,
                                     fruLocationCode);
    });
}

TEST_F(vpdManagerReaderTest, getExpandedLocationCode_Valid)
{
    // mock the call to read bus property
    MockUtilCalls uCalls;
    EXPECT_CALL(uCalls, readBusProperty(SYSTEM_OBJECT, IBM_LOCATION_CODE_INF,
                                        "LocationCode"))
        .Times(1)
        .WillOnce(testing::Return("U78DA.ND1.1234567-P0"));

    std::string unexpandedLocationCode = "Ufcs-P0";
    ReaderImpl read(uCalls);
    std::string res = read.getExpandedLocationCode(unexpandedLocationCode,
                                                   nodeNumber, fruLocationCode);

    EXPECT_EQ(res, "U78DA.ND1.1234567-P0");
}

TEST_F(vpdManagerReaderTest, getFrusAtLocation_Invalid)
{
    // invalid lication code
    std::string unexpandedLocationCode = "Uabc-X0";

    MockUtilCalls uCalls;
    ReaderImpl read(uCalls);
    EXPECT_ANY_THROW({
        read.getFrusAtLocation(unexpandedLocationCode, nodeNumber,
                               fruLocationCode);
    });

    // map to hold the mapping of location code and inventory path, empty in
    // this case
    LocationCodeMap mapLocationCode;
    unexpandedLocationCode = "Ufcs-P0";
    EXPECT_ANY_THROW({
        read.getFrusAtLocation(unexpandedLocationCode, nodeNumber,
                               mapLocationCode);
    });
}

TEST_F(vpdManagerReaderTest, getFrusAtLocation_Valid)
{
    std::string LocationCode = "Ufcs-P0";

    MockUtilCalls uCalls;
    ReaderImpl read(uCalls);
    ListOfPaths paths =
        read.getFrusAtLocation(LocationCode, nodeNumber, fruLocationCode);
    std::string expected =
        "/xyz/openbmc_project/inventory/system/chassis/motherboard";
    EXPECT_EQ(paths.at(0), expected);
}

TEST_F(vpdManagerReaderTest, getFRUsByExpandedLocationCode_invalid)
{
    // not starting from U
    std::string locationCode = "9105.22A.SIMP10R";

    MockUtilCalls uCalls;
    ReaderImpl read(uCalls);
    ListOfPaths paths;
    EXPECT_ANY_THROW({
        paths =
            read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
    });

    // unused variable warning
    (void)paths;

    // length is les sthan 17 for expanded location code
    locationCode = "U9105.22A.SIMP10";
    EXPECT_ANY_THROW({
        paths =
            read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
    });

    // Invalid location code. No "."
    locationCode = "U78DAND11234567-P0";

    // Mock readBUsproperty call
    EXPECT_CALL(uCalls,
                readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC"))
        .Times(1)
        .WillOnce(
            testing::Return("78DAPQRS")); // return a dummy value for FC keyword

    // unused variable warning
    (void)paths;
    EXPECT_ANY_THROW({
        paths =
            read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
    });
}

TEST_F(vpdManagerReaderTest, getFRUsByExpandedLocationCode_Valid_FC)
{
    // valid location code with FC kwd.
    std::string validLocationCode = "U78DA.ND1.1234567-P0";

    // Mock readBUsproperty call
    MockUtilCalls uCalls;
    EXPECT_CALL(uCalls,
                readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC"))
        .WillRepeatedly(
            testing::Return("78DAPQRS")); // return a dummy value for FC keyword

    ReaderImpl read(uCalls);
    ListOfPaths paths =
        read.getFRUsByExpandedLocationCode(validLocationCode, fruLocationCode);

    std::string expected =
        "/xyz/openbmc_project/inventory/system/chassis/motherboard";
    EXPECT_EQ(paths.at(0), expected);
}

TEST_F(vpdManagerReaderTest, getFRUsByExpandedLocationCode_Valid_TM)
{
    // valid location code with TM kwd.
    std::string validLocationCode = "U9105.22A.SIMP10R";

    // Mock readBUsproperty call
    MockUtilCalls uCalls;
    EXPECT_CALL(uCalls,
                readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC"))
        .Times(1)
        .WillOnce(
            testing::Return("78DAPQRS")); // return a dummy value for FC keyword

    EXPECT_CALL(uCalls,
                readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM"))
        .Times(1)
        .WillOnce(
            testing::Return("9105PQRS")); // return a dummy value for TM keyword

    ReaderImpl read(uCalls);
    ListOfPaths paths =
        read.getFRUsByExpandedLocationCode(validLocationCode, fruLocationCode);

    std::string expected = "/xyz/openbmc_project/inventory/system";
    EXPECT_EQ(paths.at(0), expected);
}

int main(int argc, char** argv)
{
    ::testing::InitGoogleTest(&argc, argv);

    return RUN_ALL_TESTS();
}