#include "config.h"

#include "reader_impl.hpp"

#include "utils.hpp"

#include <algorithm>
#include <com/ibm/VPD/error.hpp>
#include <map>
#include <phosphor-logging/elog-errors.hpp>
#include <vector>
#include <xyz/openbmc_project/Common/error.hpp>

#ifdef ManagerTest
#include "reader_test.hpp"
#endif

namespace openpower
{
namespace vpd
{
namespace manager
{
namespace reader
{

using namespace phosphor::logging;
using namespace openpower::vpd::inventory;
using namespace openpower::vpd::constants;
using namespace openpower::vpd::utils::interface;

using InvalidArgument =
    sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
using Argument = xyz::openbmc_project::Common::InvalidArgument;
using LocationNotFound = sdbusplus::com::ibm::VPD::Error::LocationNotFound;

bool ReaderImpl::isValidLocationCode(const LocationCode& locationCode) const
{
    if ((locationCode.length() < UNEXP_LOCATION_CODE_MIN_LENGTH) ||
        (locationCode[0] != 'U') ||
        ((locationCode.find("fcs", 1, 3) == std::string::npos) &&
         (locationCode.find("mts", 1, 3) == std::string::npos)))
    {
        return false;
    }

    return true;
}

LocationCode ReaderImpl::getExpandedLocationCode(
    const LocationCode& locationCode, const NodeNumber& nodeNumber,
    const LocationCodeMap& frusLocationCode) const
{
    // unused at this moment. Hence to avoid warnings
    (void)nodeNumber;
    if (!isValidLocationCode(locationCode))
    {
        // argument is not valid
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
    }
    auto iterator = frusLocationCode.find(locationCode);
    if (iterator == frusLocationCode.end())
    {
        // TODO: Implementation of error logic till then throwing invalid
        // argument
        // the location code was not found in the system
        // elog<LocationNotFound>();
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
    }

    std::string expandedLocationCode{};
#ifndef ManagerTest
    utility utilObj;
#endif
    expandedLocationCode = utilObj.readBusProperty(
        iterator->second, LOCATION_CODE_INF, "LocationCode");
    return expandedLocationCode;
}

ListOfPaths
    ReaderImpl::getFrusAtLocation(const LocationCode& locationCode,
                                  const NodeNumber& nodeNumber,
                                  const LocationCodeMap& frusLocationCode) const
{
    // unused at this moment, to avoid compilation warning
    (void)nodeNumber;

    // TODO:Implementation related to node number
    if (!isValidLocationCode(locationCode))
    {
        // argument is not valid
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
    }

    auto range = frusLocationCode.equal_range(locationCode);

    if (range.first == frusLocationCode.end())
    {
        // TODO: Implementation of error logic till then throwing invalid
        // argument
        // the location code was not found in the system
        // elog<LocationNotFound>();
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
    }

    ListOfPaths inventoryPaths;

    for_each(range.first, range.second,
             [&inventoryPaths](
                 const inventory::LocationCodeMap::value_type& mappedItem) {
                 inventoryPaths.push_back(INVENTORY_PATH + mappedItem.second);
             });
    return inventoryPaths;
}

std::tuple<LocationCode, NodeNumber>
    ReaderImpl::getCollapsedLocationCode(const LocationCode& locationCode) const
{
    // Location code should always start with U and fulfil minimum length
    // criteria.
    if (locationCode[0] != 'U' ||
        locationCode.length() < EXP_LOCATIN_CODE_MIN_LENGTH)
    {
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
    }

    std::string fc{};
#ifndef ManagerTest
    utility utilObj;
#endif

    fc = utilObj.readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");

    // get the first part of expanded location code to check for FC or TM
    std::string firstKeyword = locationCode.substr(1, 4);

    LocationCode unexpandedLocationCode{};
    NodeNumber nodeNummber = INVALID_NODE_NUMBER;

    // check if this value matches the value of FC kwd
    if (fc.substr(0, 4) ==
        firstKeyword) // implies this is Ufcs format location code
    {
        // period(.) should be there in expanded location code to seggregate FC,
        // Node number and SE values.
        size_t nodeStartPos = locationCode.find('.');
        if (nodeStartPos == std::string::npos)
        {
            elog<InvalidArgument>(
                Argument::ARGUMENT_NAME("LOCATIONCODE"),
                Argument::ARGUMENT_VALUE(locationCode.c_str()));
        }

        // second period(.) should be there to end the node details in non
        // system location code
        size_t nodeEndPos = locationCode.find('.', nodeStartPos + 1);
        if (nodeEndPos == std::string::npos)
        {
            elog<InvalidArgument>(
                Argument::ARGUMENT_NAME("LOCATIONCODE"),
                Argument::ARGUMENT_VALUE(locationCode.c_str()));
        }

        // skip 3 for '.ND'
        nodeNummber = std::stoi(locationCode.substr(
            nodeStartPos + 3, (nodeEndPos - nodeStartPos - 3)));

        // confirm if there are other details apart FC, Node number and SE in
        // location code
        if (locationCode.length() > EXP_LOCATIN_CODE_MIN_LENGTH)
        {
            unexpandedLocationCode =
                locationCode[0] + (std::string) "fcs" +
                locationCode.substr(nodeEndPos + 1 + SE_KWD_LENGTH,
                                    std::string::npos);
        }
        else
        {
            unexpandedLocationCode = "Ufcs";
        }
    }
    else
    {
        std::string tm{};
        // read TM kwd value
        tm =
            utilObj.readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
        ;

        // check if the substr matches to TM kwd
        if (tm.substr(0, 4) ==
            firstKeyword) // implies this is Umts format of location code
        {
            // system location code will not have any other details and node
            // number
            unexpandedLocationCode = "Umts";
        }
        // it does not belong to either "fcs" or "mts"
        else
        {
            elog<InvalidArgument>(
                Argument::ARGUMENT_NAME("LOCATIONCODE"),
                Argument::ARGUMENT_VALUE(locationCode.c_str()));
        }
    }

    return std::make_tuple(unexpandedLocationCode, nodeNummber);
}

ListOfPaths ReaderImpl::getFRUsByExpandedLocationCode(
    const inventory::LocationCode& locationCode,
    const inventory::LocationCodeMap& frusLocationCode) const
{
    std::tuple<LocationCode, NodeNumber> locationAndNodePair =
        getCollapsedLocationCode(locationCode);

    return getFrusAtLocation(std::get<0>(locationAndNodePair),
                             std::get<1>(locationAndNodePair),
                             frusLocationCode);
}
} // namespace reader
} // namespace manager
} // namespace vpd
} // namespace openpower
