#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"][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/chassis/motherboard",
                                        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();
}