#include "hyp_network_manager.hpp"

#include "types.hpp"
#include "util.hpp"

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

using sdbusplus::exception::SdBusError;

class HypNetworkMgr;

namespace phosphor
{
namespace network
{
using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;

const std::string intType = "Integer";
const std::string strType = "String";
const std::string enumType = "Enumeration";

using ObjectTree =
    std::map<std::string, std::map<std::string, std::vector<std::string>>>;

auto HypNetworkMgr::getDBusProp(const std::string& objectName,
                                const std::string& interface,
                                const std::string& kw)
{
    auto bus = sdbusplus::bus::new_default();
    auto properties = bus.new_method_call(
        "xyz.openbmc_project.BIOSConfigManager", objectName.c_str(),
        "org.freedesktop.DBus.Properties", "Get");
    properties.append(interface);
    properties.append(kw);
    auto result = bus.call(properties);

    if (result.is_method_error())
    {
        throw std::runtime_error("Get api failed");
    }
    return result;
}

void HypNetworkMgr::setBIOSTableAttr(
    std::string attrName, std::variant<std::string, int64_t> attrValue,
    std::string attrType)
{
    auto findAttr = biosTableAttrs.find(attrName);
    if (findAttr != biosTableAttrs.end())
    {
        if (attrType == intType)
        {
            int64_t value = std::get<int64_t>(attrValue);
            if (value != std::get<int64_t>(findAttr->second))
            {
                biosTableAttrs.erase(findAttr);
                biosTableAttrs.emplace(attrName, value);
            }
        }
        else if (attrType == strType)
        {
            std::string value = std::get<std::string>(attrValue);
            if (value != std::get<std::string>(findAttr->second))
            {
                biosTableAttrs.erase(findAttr);
                biosTableAttrs.emplace(attrName, value);
            }
        }
    }
    else
    {
        log<level::INFO>(
            "setBIOSTableAttr: Attribute is not found in biosTableAttrs"),
            entry("attrName : ", attrName.c_str());
    }
}

void HypNetworkMgr::setDefaultBIOSTableAttrsOnIntf(const std::string& intf)
{
    biosTableAttrs.emplace("vmi_" + intf + "_ipv4_ipaddr", "0.0.0.0");
    biosTableAttrs.emplace("vmi_" + intf + "_ipv4_gateway", "0.0.0.0");
    biosTableAttrs.emplace("vmi_" + intf + "_ipv4_prefix_length", 0);
    biosTableAttrs.emplace("vmi_" + intf + "_ipv4_method", "IPv4Static");
}

void HypNetworkMgr::setDefaultHostnameInBIOSTableAttrs()
{
    biosTableAttrs.emplace("vmi_hostname", "");
}

void HypNetworkMgr::setBIOSTableAttrs()
{
    try
    {
        constexpr auto biosMgrIntf = "xyz.openbmc_project.BIOSConfig.Manager";
        constexpr auto biosMgrObj = "/xyz/openbmc_project/bios_config";

        constexpr auto mapperBus = "xyz.openbmc_project.ObjectMapper";
        constexpr auto mapperObj = "/xyz/openbmc_project/object_mapper";
        constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";

        std::vector<std::string> interfaces;
        interfaces.emplace_back(biosMgrIntf);
        auto depth = 0;

        auto mapperCall =
            bus.new_method_call(mapperBus, mapperObj, mapperIntf, "GetSubTree");

        mapperCall.append(biosMgrObj, depth, interfaces);

        auto mapperReply = bus.call(mapperCall);
        if (mapperReply.is_method_error())
        {
            log<level::ERR>("Error in mapper call");
            elog<InternalFailure>();
        }

        ObjectTree objectTree;
        mapperReply.read(objectTree);

        if (objectTree.empty())
        {
            log<level::ERR>("No Object has implemented the interface",
                            entry("INTERFACE=%s", biosMgrIntf));
            elog<InternalFailure>();
        }

        std::string objPath;

        if (1 == objectTree.size())
        {
            objPath = objectTree.begin()->first;
        }
        else
        {
            // If there are more than 2 objects, object path must contain the
            // interface name
            for (auto const& object : objectTree)
            {
                log<level::INFO>("interface", entry("INT=%s", biosMgrIntf));
                log<level::INFO>("object",
                                 entry("OBJ=%s", object.first.c_str()));

                if (std::string::npos != object.first.find(biosMgrIntf))
                {
                    objPath = object.first;
                    break;
                }
            }

            if (objPath.empty())
            {
                log<level::ERR>("Can't find the object for the interface",
                                entry("intfName=%s", biosMgrIntf));
                elog<InternalFailure>();
            }
        }

        std::variant<BiosBaseTableType> response;
        getDBusProp(objPath, biosMgrIntf, "BaseBIOSTable").read(response);

        const BiosBaseTableType* baseBiosTable =
            std::get_if<BiosBaseTableType>(&response);

        if (baseBiosTable == nullptr)
        {
            log<level::ERR>("BaseBiosTable is empty. No attributes found!");
            return;
        }

        for (const BiosBaseTableItemType& item : *baseBiosTable)
        {
            if (item.first.rfind("vmi", 0) == 0) // starts with the prefix
            {
                const std::string& itemType =
                    std::get<biosBaseAttrType>(item.second);

                if (itemType.compare(itemType.size() - intType.size(),
                                     intType.size(), intType) == 0)
                {
                    const int64_t* currValue = std::get_if<int64_t>(
                        &std::get<biosBaseCurrValue>(item.second));
                    if (currValue != nullptr)
                    {
                        biosTableAttrs.emplace(item.first, *currValue);
                    }
                }
                else if ((itemType.compare(itemType.size() - strType.size(),
                                           strType.size(), strType) == 0) ||
                         (itemType.compare(itemType.size() - enumType.size(),
                                           enumType.size(), enumType) == 0))
                {
                    const std::string* currValue = std::get_if<std::string>(
                        &std::get<biosBaseCurrValue>(item.second));
                    if (currValue != nullptr)
                    {
                        biosTableAttrs.emplace(item.first, *currValue);
                    }
                }
                else
                {
                    log<level::ERR>("Unsupported datatype: The attribute is of "
                                    "unknown type");
                }
            }
        }
    }
    catch (const SdBusError& e)
    {
        log<level::ERR>("Error in making dbus call");
        throw std::runtime_error("DBus call failed");
    }
}

biosTableType HypNetworkMgr::getBIOSTableAttrs()
{
    return biosTableAttrs;
}

void HypNetworkMgr::createIfObjects()
{
    setBIOSTableAttrs();

    if ((getBIOSTableAttrs()).size() == 0)
    {
        setDefaultHostnameInBIOSTableAttrs();
    }

    // The hypervisor can support maximum of
    // 2 ethernet interfaces. Both eth0/1 objects are
    // created during init time to support the static
    // network configurations on the both.
    // create eth0 and eth1 objects
    log<level::INFO>("Create eth0 and eth1 objects");
}

void HypNetworkMgr::createSysConfObj()
{
    systemConf.reset(nullptr);
    this->systemConf = std::make_unique<phosphor::network::HypSysConfig>(
        bus, objectPath + "/config", *this);
}

} // namespace network
} // namespace phosphor
