// 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 "phosphor-logging/lg2.hpp"
#include "topology.hpp"
#include "utils.hpp"

#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.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 <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>

#include <filesystem>
#include <fstream>
#include <functional>
#include <iostream>
#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),
    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(newBoards))
    {
        auto findBoard = newBoards.find(assocPath);
        if (findBoard == newBoards.end())
        {
            continue;
        }

        auto ifacePtr = dbus_interface.createInterface(
            objServer, 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
    {
        std::cerr << "Unable to find type for " << boardName
                  << " reverting to Chassis.\n";
        boardType = "Chassis";
    }
    std::string boardtypeLower = boost::algorithm::to_lower_copy(boardType);

    std::regex_replace(boardName.begin(), boardName.begin(), boardName.end(),
                       illegalDbusMemberRegex, "_");
    std::string boardPath = "/xyz/openbmc_project/inventory/system/";
    boardPath += boardtypeLower;
    boardPath += "/";
    boardPath += boardName;

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

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

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

    dbus_interface::populateInterfaceFromJson(
        io, systemConfiguration, jsonPointerPath, boardIface, boardValues,
        objServer);
    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(objServer, boardPath, propName,
                                               boardNameOrig);

            dbus_interface::populateInterfaceFromJson(
                io, systemConfiguration, jsonPointerPath + propName, iface,
                propValue, objServer);
        }
    }

    auto 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 (auto& item : *exposes)
    {
        exposesIndex++;
        jsonPointerPath = jsonPointerPathBoard;
        jsonPointerPath += std::to_string(exposesIndex);

        auto findName = item.find("Name");
        if (findName == item.end())
        {
            std::cerr << "cannot find name in field " << item << "\n";
            continue;
        }
        auto findStatus = item.find("Status");
        // if status is not found it is assumed to be status = 'okay'
        if (findStatus != item.end())
        {
            if (*findStatus == "disabled")
            {
                continue;
            }
        }
        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(
                    objServer, ifacePath,
                    "xyz.openbmc_project.Inventory.Item.Bmc", boardNameOrig);
            dbus_interface::populateInterfaceFromJson(
                io, systemConfiguration, jsonPointerPath, bmcIface, item,
                objServer, getPermission(itemType));
        }
        else if (itemType == "System")
        {
            std::shared_ptr<sdbusplus::asio::dbus_interface> systemIface =
                dbus_interface.createInterface(
                    objServer, ifacePath,
                    "xyz.openbmc_project.Inventory.Item.System", boardNameOrig);
            dbus_interface::populateInterfaceFromJson(
                io, systemConfiguration, jsonPointerPath, systemIface, item,
                objServer, getPermission(itemType));
        }

        for (const auto& [name, config] : item.items())
        {
            jsonPointerPath = jsonPointerPathBoard;
            jsonPointerPath.append(std::to_string(exposesIndex))
                .append("/")
                .append(name);
            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(objServer, ifacePath,
                                                   ifaceName, boardNameOrig);

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

                // verify legal json
                for (const auto& arrayItem : config)
                {
                    if (arrayItem.type() != type)
                    {
                        isLegal = false;
                        break;
                    }
                }
                if (!isLegal)
                {
                    std::cerr << "dbus format error" << config << "\n";
                    break;
                }

                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(
                            objServer, ifacePath, ifaceName, boardNameOrig);

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

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

        dbus_interface::populateInterfaceFromJson(
            io, systemConfiguration, jsonPointerPath, itemIface, item,
            objServer, getPermission(itemType));

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

    newBoards.emplace(boardPath, boardNameOrig);
}

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))
        {
            std::cerr << "Error writing json files\n";
        }
    });

    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)
            {
                std::cerr << "async wait error " << ec << "\n";
                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;
    std::set<std::string> interfaceSet;
    std::set<std::string> intersect;

    msg.read(path, interfaces);

    std::for_each(interfaces.begin(), interfaces.end(),
                  [&interfaceSet](const auto& iface) {
                      interfaceSet.insert(iface.first);
                  });

    std::set_intersection(interfaceSet.begin(), interfaceSet.end(),
                          probeInterfaces.begin(), probeInterfaces.end(),
                          std::inserter(intersect, intersect.end()));
    return !intersect.empty();
}

// 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::set<std::string> interfaces;
    std::set<std::string> intersect;

    msg.read(path, interfaces);

    std::set_intersection(interfaces.begin(), interfaces.end(),
                          probeInterfaces.begin(), probeInterfaces.end(),
                          std::inserter(intersect, intersect.end()));
    return !intersect.empty();
}

void EntityManager::handleCurrentConfigurationJson()
{
    if (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())
                {
                    std::cerr
                        << "syntax error in " << lastConfiguration << "\n";
                }
                else
                {
                    lastJson = std::move(data);
                }
            }
            else
            {
                std::cerr << "unable to open " << lastConfiguration << "\n";
            }
        }
    }
    else
    {
        // not an error, just logging at this level to make it in the journal
        std::cerr << "Clearing previous configuration\n";
        std::filesystem::remove(currentConfiguration);
    }
}

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();
            }
        });
}
