// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation

#include "entity_manager.hpp"

#include "../utils.hpp"
#include "../variant_visitors.hpp"
#include "configuration.hpp"
#include "dbus_interface.hpp"
#include "log_device_inventory.hpp"
#include "overlay.hpp"
#include "perform_scan.hpp"
#include "topology.hpp"
#include "utils.hpp"

#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/range/iterator_range.hpp>
#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>

#include <filesystem>
#include <fstream>
#include <functional>
#include <map>
#include <regex>
constexpr const char* tempConfigDir = "/tmp/configuration/";
constexpr const char* lastConfiguration = "/tmp/configuration/last.json";

static constexpr std::array<const char*, 6> settableInterfaces = {
    "FanProfile", "Pid", "Pid.Zone", "Stepwise", "Thresholds", "Polling"};

const std::regex illegalDbusPathRegex("[^A-Za-z0-9_.]");
const std::regex illegalDbusMemberRegex("[^A-Za-z0-9_]");

sdbusplus::asio::PropertyPermission getPermission(const std::string& interface)
{
    return std::find(settableInterfaces.begin(), settableInterfaces.end(),
                     interface) != settableInterfaces.end()
               ? sdbusplus::asio::PropertyPermission::readWrite
               : sdbusplus::asio::PropertyPermission::readOnly;
}

EntityManager::EntityManager(
    std::shared_ptr<sdbusplus::asio::connection>& systemBus,
    boost::asio::io_context& io) :
    systemBus(systemBus),
    objServer(sdbusplus::asio::object_server(systemBus, /*skipManager=*/true)),
    lastJson(nlohmann::json::object()),
    systemConfiguration(nlohmann::json::object()), io(io),
    dbus_interface(io, objServer), powerStatus(*systemBus),
    propertiesChangedTimer(io)
{
    // All other objects that EntityManager currently support are under the
    // inventory subtree.
    // See the discussion at
    // https://discord.com/channels/775381525260664832/1018929092009144380
    objServer.add_manager("/xyz/openbmc_project/inventory");

    entityIface = objServer.add_interface("/xyz/openbmc_project/EntityManager",
                                          "xyz.openbmc_project.EntityManager");
    entityIface->register_method("ReScan", [this]() {
        propertiesChangedCallback();
    });
    dbus_interface::tryIfaceInitialize(entityIface);

    initFilters(configuration.probeInterfaces);
}

void EntityManager::postToDbus(const nlohmann::json& newConfiguration)
{
    std::map<std::string, std::string> newBoards; // path -> name

    // iterate through boards
    for (const auto& [boardId, boardConfig] : newConfiguration.items())
    {
        postBoardToDBus(boardId, boardConfig, newBoards);
    }

    for (const auto& [assocPath, assocPropValue] :
         topology.getAssocs(std::views::keys(newBoards)))
    {
        auto findBoard = newBoards.find(assocPath);
        if (findBoard == newBoards.end())
        {
            continue;
        }

        auto ifacePtr = dbus_interface.createInterface(
            assocPath, "xyz.openbmc_project.Association.Definitions",
            findBoard->second);

        ifacePtr->register_property("Associations", assocPropValue);
        dbus_interface::tryIfaceInitialize(ifacePtr);
    }
}

void EntityManager::postBoardToDBus(
    const std::string& boardId, const nlohmann::json& boardConfig,
    std::map<std::string, std::string>& newBoards)
{
    std::string boardName = boardConfig["Name"];
    std::string boardNameOrig = boardConfig["Name"];
    std::string jsonPointerPath = "/" + boardId;
    // loop through newConfiguration, but use values from system
    // configuration to be able to modify via dbus later
    auto boardValues = systemConfiguration[boardId];
    auto findBoardType = boardValues.find("Type");
    std::string boardType;
    if (findBoardType != boardValues.end() &&
        findBoardType->type() == nlohmann::json::value_t::string)
    {
        boardType = findBoardType->get<std::string>();
        std::regex_replace(boardType.begin(), boardType.begin(),
                           boardType.end(), illegalDbusMemberRegex, "_");
    }
    else
    {
        lg2::error("Unable to find type for {BOARD} reverting to Chassis.",
                   "BOARD", boardName);
        boardType = "Chassis";
    }

    const std::string boardPath =
        em_utils::buildInventorySystemPath(boardName, boardType);

    std::shared_ptr<sdbusplus::asio::dbus_interface> inventoryIface =
        dbus_interface.createInterface(
            boardPath, "xyz.openbmc_project.Inventory.Item", boardName);

    std::shared_ptr<sdbusplus::asio::dbus_interface> boardIface =
        dbus_interface.createInterface(
            boardPath, "xyz.openbmc_project.Inventory.Item." + boardType,
            boardNameOrig);

    dbus_interface.createAddObjectMethod(jsonPointerPath, boardPath,
                                         systemConfiguration, boardNameOrig);

    dbus_interface.populateInterfaceFromJson(
        systemConfiguration, jsonPointerPath, boardIface, boardValues);
    jsonPointerPath += "/";
    // iterate through board properties
    for (const auto& [propName, propValue] : boardValues.items())
    {
        if (propValue.type() == nlohmann::json::value_t::object)
        {
            std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
                dbus_interface.createInterface(boardPath, propName,
                                               boardNameOrig);

            dbus_interface.populateInterfaceFromJson(
                systemConfiguration, jsonPointerPath + propName, iface,
                propValue);
        }
    }

    nlohmann::json::iterator exposes = boardValues.find("Exposes");
    if (exposes == boardValues.end())
    {
        return;
    }
    // iterate through exposes
    jsonPointerPath += "Exposes/";

    // store the board level pointer so we can modify it on the way down
    std::string jsonPointerPathBoard = jsonPointerPath;
    size_t exposesIndex = -1;
    for (nlohmann::json& item : *exposes)
    {
        postExposesRecordsToDBus(item, exposesIndex, boardNameOrig,
                                 jsonPointerPath, jsonPointerPathBoard,
                                 boardPath, boardType);
    }

    newBoards.emplace(boardPath, boardNameOrig);
}

void EntityManager::postExposesRecordsToDBus(
    nlohmann::json& item, size_t& exposesIndex,
    const std::string& boardNameOrig, std::string jsonPointerPath,
    const std::string& jsonPointerPathBoard, const std::string& boardPath,
    const std::string& boardType)
{
    exposesIndex++;
    jsonPointerPath = jsonPointerPathBoard;
    jsonPointerPath += std::to_string(exposesIndex);

    auto findName = item.find("Name");
    if (findName == item.end())
    {
        lg2::error("cannot find name in field {ITEM}", "ITEM", item);
        return;
    }
    auto findStatus = item.find("Status");
    // if status is not found it is assumed to be status = 'okay'
    if (findStatus != item.end())
    {
        if (*findStatus == "disabled")
        {
            return;
        }
    }
    auto findType = item.find("Type");
    std::string itemType;
    if (findType != item.end())
    {
        itemType = findType->get<std::string>();
        std::regex_replace(itemType.begin(), itemType.begin(), itemType.end(),
                           illegalDbusPathRegex, "_");
    }
    else
    {
        itemType = "unknown";
    }
    std::string itemName = findName->get<std::string>();
    std::regex_replace(itemName.begin(), itemName.begin(), itemName.end(),
                       illegalDbusMemberRegex, "_");
    std::string ifacePath = boardPath;
    ifacePath += "/";
    ifacePath += itemName;

    if (itemType == "BMC")
    {
        std::shared_ptr<sdbusplus::asio::dbus_interface> bmcIface =
            dbus_interface.createInterface(
                ifacePath, "xyz.openbmc_project.Inventory.Item.Bmc",
                boardNameOrig);
        dbus_interface.populateInterfaceFromJson(
            systemConfiguration, jsonPointerPath, bmcIface, item,
            getPermission(itemType));
    }
    else if (itemType == "System")
    {
        std::shared_ptr<sdbusplus::asio::dbus_interface> systemIface =
            dbus_interface.createInterface(
                ifacePath, "xyz.openbmc_project.Inventory.Item.System",
                boardNameOrig);
        dbus_interface.populateInterfaceFromJson(
            systemConfiguration, jsonPointerPath, systemIface, item,
            getPermission(itemType));
    }

    for (const auto& [name, config] : item.items())
    {
        jsonPointerPath = jsonPointerPathBoard;
        jsonPointerPath.append(std::to_string(exposesIndex))
            .append("/")
            .append(name);

        if (!postConfigurationRecord(name, config, boardNameOrig, itemType,
                                     jsonPointerPath, ifacePath))
        {
            break;
        }
    }

    std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface =
        dbus_interface.createInterface(
            ifacePath, "xyz.openbmc_project.Configuration." + itemType,
            boardNameOrig);

    dbus_interface.populateInterfaceFromJson(
        systemConfiguration, jsonPointerPath, itemIface, item,
        getPermission(itemType));

    topology.addBoard(boardPath, boardType, boardNameOrig, item);
}

bool EntityManager::postConfigurationRecord(
    const std::string& name, nlohmann::json& config,
    const std::string& boardNameOrig, const std::string& itemType,
    const std::string& jsonPointerPath, const std::string& ifacePath)
{
    if (config.type() == nlohmann::json::value_t::object)
    {
        std::string ifaceName = "xyz.openbmc_project.Configuration.";
        ifaceName.append(itemType).append(".").append(name);

        std::shared_ptr<sdbusplus::asio::dbus_interface> objectIface =
            dbus_interface.createInterface(ifacePath, ifaceName, boardNameOrig);

        dbus_interface.populateInterfaceFromJson(
            systemConfiguration, jsonPointerPath, objectIface, config,
            getPermission(name));
    }
    else if (config.type() == nlohmann::json::value_t::array)
    {
        size_t index = 0;
        if (config.empty())
        {
            return true;
        }
        bool isLegal = true;
        auto type = config[0].type();
        if (type != nlohmann::json::value_t::object)
        {
            return true;
        }

        // verify legal json
        for (const auto& arrayItem : config)
        {
            if (arrayItem.type() != type)
            {
                isLegal = false;
                break;
            }
        }
        if (!isLegal)
        {
            lg2::error("dbus format error {JSON}", "JSON", config);
            return false;
        }

        for (auto& arrayItem : config)
        {
            std::string ifaceName = "xyz.openbmc_project.Configuration.";
            ifaceName.append(itemType).append(".").append(name);
            ifaceName.append(std::to_string(index));

            std::shared_ptr<sdbusplus::asio::dbus_interface> objectIface =
                dbus_interface.createInterface(ifacePath, ifaceName,
                                               boardNameOrig);

            dbus_interface.populateInterfaceFromJson(
                systemConfiguration,
                jsonPointerPath + "/" + std::to_string(index), objectIface,
                arrayItem, getPermission(name));
            index++;
        }
    }

    return true;
}

static bool deviceRequiresPowerOn(const nlohmann::json& entity)
{
    auto powerState = entity.find("PowerState");
    if (powerState == entity.end())
    {
        return false;
    }

    const auto* ptr = powerState->get_ptr<const std::string*>();
    if (ptr == nullptr)
    {
        return false;
    }

    return *ptr == "On" || *ptr == "BiosPost";
}

static void pruneDevice(const nlohmann::json& systemConfiguration,
                        const bool powerOff, const bool scannedPowerOff,
                        const std::string& name, const nlohmann::json& device)
{
    if (systemConfiguration.contains(name))
    {
        return;
    }

    if (deviceRequiresPowerOn(device) && (powerOff || scannedPowerOff))
    {
        return;
    }

    logDeviceRemoved(device);
}

void EntityManager::startRemovedTimer(boost::asio::steady_timer& timer,
                                      nlohmann::json& systemConfiguration)
{
    if (systemConfiguration.empty() || lastJson.empty())
    {
        return; // not ready yet
    }
    if (scannedPowerOn)
    {
        return;
    }

    if (!powerStatus.isPowerOn() && scannedPowerOff)
    {
        return;
    }

    timer.expires_after(std::chrono::seconds(10));
    timer.async_wait(
        [&systemConfiguration, this](const boost::system::error_code& ec) {
            if (ec == boost::asio::error::operation_aborted)
            {
                return;
            }

            bool powerOff = !powerStatus.isPowerOn();
            for (const auto& [name, device] : lastJson.items())
            {
                pruneDevice(systemConfiguration, powerOff, scannedPowerOff,
                            name, device);
            }

            scannedPowerOff = true;
            if (!powerOff)
            {
                scannedPowerOn = true;
            }
        });
}

void EntityManager::pruneConfiguration(bool powerOff, const std::string& name,
                                       const nlohmann::json& device)
{
    if (powerOff && deviceRequiresPowerOn(device))
    {
        // power not on yet, don't know if it's there or not
        return;
    }

    auto& ifaces = dbus_interface.getDeviceInterfaces(device);
    for (auto& iface : ifaces)
    {
        auto sharedPtr = iface.lock();
        if (!!sharedPtr)
        {
            objServer.remove_interface(sharedPtr);
        }
    }

    ifaces.clear();
    systemConfiguration.erase(name);
    topology.remove(device["Name"].get<std::string>());
    logDeviceRemoved(device);
}

void EntityManager::publishNewConfiguration(
    const size_t& instance, const size_t count,
    boost::asio::steady_timer& timer, // Gerrit discussion:
    // https://gerrit.openbmc-project.xyz/c/openbmc/entity-manager/+/52316/6
    //
    // Discord discussion:
    // https://discord.com/channels/775381525260664832/867820390406422538/958048437729910854
    //
    // NOLINTNEXTLINE(performance-unnecessary-value-param)
    const nlohmann::json newConfiguration)
{
    loadOverlays(newConfiguration, io);

    boost::asio::post(io, [this]() {
        if (!writeJsonFiles(systemConfiguration))
        {
            lg2::error("Error writing json files");
        }
    });

    boost::asio::post(io, [this, &instance, count, &timer, newConfiguration]() {
        postToDbus(newConfiguration);
        if (count == instance)
        {
            startRemovedTimer(timer, systemConfiguration);
        }
    });
}

// main properties changed entry
void EntityManager::propertiesChangedCallback()
{
    propertiesChangedInstance++;
    size_t count = propertiesChangedInstance;

    propertiesChangedTimer.expires_after(std::chrono::milliseconds(500));

    // setup an async wait as we normally get flooded with new requests
    propertiesChangedTimer.async_wait(
        [this, count](const boost::system::error_code& ec) {
            if (ec == boost::asio::error::operation_aborted)
            {
                // we were cancelled
                return;
            }
            if (ec)
            {
                lg2::error("async wait error {ERR}", "ERR", ec.message());
                return;
            }

            if (propertiesChangedInProgress)
            {
                propertiesChangedCallback();
                return;
            }
            propertiesChangedInProgress = true;

            nlohmann::json oldConfiguration = systemConfiguration;
            auto missingConfigurations = std::make_shared<nlohmann::json>();
            *missingConfigurations = systemConfiguration;

            auto perfScan = std::make_shared<scan::PerformScan>(
                *this, *missingConfigurations, configuration.configurations, io,
                [this, count, oldConfiguration, missingConfigurations]() {
                    // this is something that since ac has been applied to the
                    // bmc we saw, and we no longer see it
                    bool powerOff = !powerStatus.isPowerOn();
                    for (const auto& [name, device] :
                         missingConfigurations->items())
                    {
                        pruneConfiguration(powerOff, name, device);
                    }
                    nlohmann::json newConfiguration = systemConfiguration;

                    deriveNewConfiguration(oldConfiguration, newConfiguration);

                    for (const auto& [_, device] : newConfiguration.items())
                    {
                        logDeviceAdded(device);
                    }

                    propertiesChangedInProgress = false;

                    boost::asio::post(io, [this, newConfiguration, count] {
                        publishNewConfiguration(
                            std::ref(propertiesChangedInstance), count,
                            std::ref(propertiesChangedTimer), newConfiguration);
                    });
                });
            perfScan->run();
        });
}

// Check if InterfacesAdded payload contains an iface that needs probing.
static bool iaContainsProbeInterface(
    sdbusplus::message_t& msg,
    const std::unordered_set<std::string>& probeInterfaces)
{
    sdbusplus::message::object_path path;
    DBusObject interfaces;
    msg.read(path, interfaces);
    return std::ranges::any_of(interfaces | std::views::keys,
                               [&probeInterfaces](const auto& ifaceName) {
                                   return probeInterfaces.contains(ifaceName);
                               });
}

// Check if InterfacesRemoved payload contains an iface that needs probing.
static bool irContainsProbeInterface(
    sdbusplus::message_t& msg,
    const std::unordered_set<std::string>& probeInterfaces)
{
    sdbusplus::message::object_path path;
    std::vector<std::string> interfaces;
    msg.read(path, interfaces);
    return std::ranges::any_of(interfaces,
                               [&probeInterfaces](const auto& ifaceName) {
                                   return probeInterfaces.contains(ifaceName);
                               });
}

void EntityManager::handleCurrentConfigurationJson()
{
    if (EM_CACHE_CONFIGURATION && em_utils::fwVersionIsSame())
    {
        if (std::filesystem::is_regular_file(currentConfiguration))
        {
            // this file could just be deleted, but it's nice for debug
            std::filesystem::create_directory(tempConfigDir);
            std::filesystem::remove(lastConfiguration);
            std::filesystem::copy(currentConfiguration, lastConfiguration);
            std::filesystem::remove(currentConfiguration);

            std::ifstream jsonStream(lastConfiguration);
            if (jsonStream.good())
            {
                auto data = nlohmann::json::parse(jsonStream, nullptr, false);
                if (data.is_discarded())
                {
                    lg2::error("syntax error in {PATH}", "PATH",
                               lastConfiguration);
                }
                else
                {
                    lastJson = std::move(data);
                }
            }
            else
            {
                lg2::error("unable to open {PATH}", "PATH", lastConfiguration);
            }
        }
    }
    else
    {
        // not an error, just logging at this level to make it in the journal
        std::error_code ec;
        lg2::error("Clearing previous configuration");
        std::filesystem::remove(currentConfiguration, ec);
    }
}

void EntityManager::registerCallback(const std::string& path)
{
    if (dbusMatches.contains(path))
    {
        return;
    }

    lg2::debug("creating PropertiesChanged match on {PATH}", "PATH", path);

    std::function<void(sdbusplus::message_t & message)> eventHandler =
        [&](sdbusplus::message_t&) { propertiesChangedCallback(); };

    sdbusplus::bus::match_t match(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        "type='signal',member='PropertiesChanged',path='" + path + "'",
        eventHandler);
    dbusMatches.emplace(path, std::move(match));
}

// We need a poke from DBus for static providers that create all their
// objects prior to claiming a well-known name, and thus don't emit any
// org.freedesktop.DBus.Properties signals.  Similarly if a process exits
// for any reason, expected or otherwise, we'll need a poke to remove
// entities from DBus.
void EntityManager::initFilters(
    const std::unordered_set<std::string>& probeInterfaces)
{
    nameOwnerChangedMatch = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::nameOwnerChanged(),
        [this](sdbusplus::message_t& m) {
            auto [name, oldOwner,
                  newOwner] = m.unpack<std::string, std::string, std::string>();

            if (name.starts_with(':'))
            {
                // We should do nothing with unique-name connections.
                return;
            }

            propertiesChangedCallback();
        });

    // We also need a poke from DBus when new interfaces are created or
    // destroyed.
    interfacesAddedMatch = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::interfacesAdded(),
        [this, probeInterfaces](sdbusplus::message_t& msg) {
            if (iaContainsProbeInterface(msg, probeInterfaces))
            {
                propertiesChangedCallback();
            }
        });

    interfacesRemovedMatch = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::interfacesRemoved(),
        [this, probeInterfaces](sdbusplus::message_t& msg) {
            if (irContainsProbeInterface(msg, probeInterfaces))
            {
                propertiesChangedCallback();
            }
        });
}
