#include "config.h"

#include "reader_impl.hpp"

#include "ibm_vpd_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, IBM_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
