#include "config.h"

#include "network_manager.hpp"

#include "config_parser.hpp"
#include "ipaddress.hpp"
#include "system_queries.hpp"
#include "types.hpp"

#include <filesystem>
#include <fstream>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

constexpr char SYSTEMD_BUSNAME[] = "org.freedesktop.systemd1";
constexpr char SYSTEMD_PATH[] = "/org/freedesktop/systemd1";
constexpr char SYSTEMD_INTERFACE[] = "org.freedesktop.systemd1.Manager";
constexpr auto FirstBootFile = "/var/lib/network/firstBoot_";

constexpr char NETWORKD_BUSNAME[] = "org.freedesktop.network1";
constexpr char NETWORKD_PATH[] = "/org/freedesktop/network1";
constexpr char NETWORKD_INTERFACE[] = "org.freedesktop.network1.Manager";

namespace phosphor
{
namespace network
{

extern std::unique_ptr<Timer> refreshObjectTimer;
extern std::unique_ptr<Timer> reloadTimer;
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using Argument = xyz::openbmc_project::Common::InvalidArgument;

Manager::Manager(sdbusplus::bus_t& bus, const char* objPath,
                 const fs::path& confDir) :
    details::VLANCreateIface(bus, objPath,
                             details::VLANCreateIface::action::defer_emit),
    bus(bus), objectPath(objPath)
{
    setConfDir(confDir);
}

void Manager::setConfDir(const fs::path& dir)
{
    confDir = dir;

    if (!fs::exists(confDir))
    {
        if (!fs::create_directories(confDir))
        {
            log<level::ERR>("Unable to create the network conf dir",
                            entry("DIR=%s", confDir.c_str()));
            elog<InternalFailure>();
        }
    }
}

void Manager::createInterfaces()
{
    // clear all the interfaces first
    interfaces.clear();
    interfacesByIdx.clear();
    for (auto& interface : system::getInterfaces())
    {
        config::Parser config(
            config::pathForIntfConf(confDir, *interface.name));
        auto intf = std::make_unique<EthernetInterface>(bus, *this, interface,
                                                        objectPath, config);
        intf->createIPAddressObjects();
        intf->createStaticNeighborObjects();
        intf->loadNameServers(config);
        intf->loadNTPServers(config);
        auto ptr = intf.get();
        interfaces.emplace(std::move(*interface.name), std::move(intf));
        interfacesByIdx.emplace(interface.idx, ptr);
    }
}

void Manager::createChildObjects()
{
    routeTable.refresh();

    // creates the ethernet interface dbus object.
    createInterfaces();

    systemConf.reset(nullptr);
    dhcpConf.reset(nullptr);

    fs::path objPath = objectPath;
    objPath /= "config";

    // create the system conf object.
    systemConf = std::make_unique<phosphor::network::SystemConfiguration>(
        bus, objPath.string());
    // create the dhcp conf object.
    objPath /= "dhcp";
    dhcpConf = std::make_unique<phosphor::network::dhcp::Configuration>(
        bus, objPath.string(), *this);
}

ObjectPath Manager::vlan(std::string interfaceName, uint32_t id)
{
    if (id == 0 || id >= 4095)
    {
        log<level::ERR>("VLAN ID is not valid", entry("VLANID=%u", id));
        elog<InvalidArgument>(
            Argument::ARGUMENT_NAME("VLANId"),
            Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
    }

    auto it = interfaces.find(interfaceName);
    if (it == interfaces.end())
    {
        using ResourceErr =
            phosphor::logging::xyz::openbmc_project::Common::ResourceNotFound;
        elog<ResourceNotFound>(ResourceErr::RESOURCE(interfaceName.c_str()));
    }
    return it->second->createVLAN(id);
}

void Manager::reset()
{
    if (fs::is_directory(confDir))
    {
        for (const auto& file : fs::directory_iterator(confDir))
        {
            fs::remove(file.path());
        }
    }
    log<level::INFO>("Network Factory Reset queued.");
}

// Need to merge the below function with the code which writes the
// config file during factory reset.
// TODO openbmc/openbmc#1751
void Manager::writeToConfigurationFile()
{
    // write all the static ip address in the systemd-network conf file
    for (const auto& intf : interfaces)
    {
        intf.second->writeConfigurationFile();
    }
}

#ifdef SYNC_MAC_FROM_INVENTORY
void Manager::setFistBootMACOnInterface(
    const std::pair<std::string, std::string>& inventoryEthPair)
{
    for (const auto& interface : interfaces)
    {
        if (interface.first == inventoryEthPair.first)
        {
            auto returnMAC =
                interface.second->macAddress(inventoryEthPair.second);
            if (returnMAC == inventoryEthPair.second)
            {
                log<level::INFO>("Set the MAC on "),
                    entry("interface : ", interface.first.c_str()),
                    entry("MAC : ", inventoryEthPair.second.c_str());
                std::error_code ec;
                if (std::filesystem::is_directory("/var/lib/network", ec))
                {
                    std::ofstream persistentFile(FirstBootFile +
                                                 interface.first);
                }
                break;
            }
            else
            {
                log<level::INFO>("MAC is Not Set on ethernet Interface");
            }
        }
    }
}

#endif

void Manager::reloadConfigsNoRefresh()
{
    reloadTimer->restartOnce(reloadTimeout);
}

void Manager::reloadConfigs()
{
    reloadConfigsNoRefresh();
    // Ensure that the next refresh happens after reconfiguration
    refreshObjectTimer->setRemaining(reloadTimeout + refreshTimeout);
}

void Manager::doReloadConfigs()
{
    for (auto& hook : reloadPreHooks)
    {
        try
        {
            hook();
        }
        catch (const std::exception& ex)
        {
            log<level::ERR>("Failed executing reload hook, ignoring",
                            entry("ERR=%s", ex.what()));
        }
    }
    reloadPreHooks.clear();
    try
    {
        auto method = bus.new_method_call(NETWORKD_BUSNAME, NETWORKD_PATH,
                                          NETWORKD_INTERFACE, "Reload");
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception_t& ex)
    {
        log<level::ERR>("Failed to reload configuration",
                        entry("ERR=%s", ex.what()));
        elog<InternalFailure>();
    }
    // Ensure reconfiguration has enough time
    if (refreshObjectTimer->isEnabled())
    {
        refreshObjectTimer->setRemaining(refreshTimeout);
    }
}

} // namespace network
} // namespace phosphor
