#include "associations.hpp"
#include "handler.hpp"
#include "processing.hpp"
#include "types.hpp"

#include <tinyxml2.h>

#include <boost/asio/io_context.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/container/flat_map.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

#include <atomic>
#include <chrono>
#include <exception>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
#include <utility>

AssociationMaps associationMaps;

void updateOwners(sdbusplus::asio::connection* conn,
                  boost::container::flat_map<std::string, std::string>& owners,
                  const std::string& newObject)
{
    if (newObject.starts_with(":"))
    {
        return;
    }
    conn->async_method_call(
        [&, newObject](const boost::system::error_code ec,
                       const std::string& nameOwner) {
        if (ec)
        {
            std::cerr << "Error getting owner of " << newObject << " : " << ec
                      << "\n";
            return;
        }
        owners[nameOwner] = newObject;
        },
        "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "GetNameOwner",
        newObject);
}

void sendIntrospectionCompleteSignal(sdbusplus::asio::connection* systemBus,
                                     const std::string& processName)
{
    // TODO(ed) This signal doesn't get exposed properly in the
    // introspect right now.  Find out how to register signals in
    // sdbusplus
    sdbusplus::message_t m = systemBus->new_signal(
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper.Private", "IntrospectionComplete");
    m.append(processName);
    m.signal_send();
}

struct InProgressIntrospect
{
    InProgressIntrospect() = delete;
    InProgressIntrospect(const InProgressIntrospect&) = delete;
    InProgressIntrospect(InProgressIntrospect&&) = delete;
    InProgressIntrospect& operator=(const InProgressIntrospect&) = delete;
    InProgressIntrospect& operator=(InProgressIntrospect&&) = delete;
    InProgressIntrospect(
        sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
        const std::string& processName, AssociationMaps& am
#ifdef MAPPER_ENABLE_DEBUG
        ,
        std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
            globalStartTime
#endif
        ) :
        systemBus(systemBus),
        io(io), processName(processName), assocMaps(am)
#ifdef MAPPER_ENABLE_DEBUG
        ,
        globalStartTime(std::move(globalStartTime)),
        processStartTime(std::chrono::steady_clock::now())
#endif
    {}
    ~InProgressIntrospect()
    {
        try
        {
            sendIntrospectionCompleteSignal(systemBus, processName);
#ifdef MAPPER_ENABLE_DEBUG
            std::chrono::duration<float> diff =
                std::chrono::steady_clock::now() - processStartTime;
            std::cout << std::setw(50) << processName << " scan took "
                      << diff.count() << " seconds\n";

            // If we're the last outstanding caller globally, calculate the
            // time it took
            if (globalStartTime != nullptr && globalStartTime.use_count() == 1)
            {
                diff = std::chrono::steady_clock::now() - *globalStartTime;
                std::cout << "Total scan took " << diff.count()
                          << " seconds to complete\n";
            }
#endif
        }
        catch (const std::exception& e)
        {
            std::cerr
                << "Terminating, unhandled exception while introspecting: "
                << e.what() << "\n";
            std::terminate();
        }
        catch (...)
        {
            std::cerr
                << "Terminating, unhandled exception while introspecting\n";
            std::terminate();
        }
    }
    sdbusplus::asio::connection* systemBus;
    boost::asio::io_context& io;
    std::string processName;
    AssociationMaps& assocMaps;
#ifdef MAPPER_ENABLE_DEBUG
    std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
        globalStartTime;
    std::chrono::time_point<std::chrono::steady_clock> processStartTime;
#endif
};

void doAssociations(boost::asio::io_context& io,
                    sdbusplus::asio::connection* systemBus,
                    InterfaceMapType& interfaceMap,
                    sdbusplus::asio::object_server& objectServer,
                    const std::string& processName, const std::string& path,
                    int timeoutRetries = 0)
{
    constexpr int maxTimeoutRetries = 3;
    systemBus->async_method_call(
        [&io, &objectServer, path, processName, &interfaceMap, systemBus,
         timeoutRetries](
            const boost::system::error_code ec,
            const std::variant<std::vector<Association>>& variantAssociations) {
        if (ec)
        {
            if (ec.value() == boost::system::errc::timed_out &&
                timeoutRetries < maxTimeoutRetries)
            {
                doAssociations(io, systemBus, interfaceMap, objectServer,
                               processName, path, timeoutRetries + 1);
                return;
            }
            std::cerr << "Error getting associations from " << path << "\n";
        }
        std::vector<Association> associations =
            std::get<std::vector<Association>>(variantAssociations);
        associationChanged(io, objectServer, associations, path, processName,
                           interfaceMap, associationMaps);
        },
        processName, path, "org.freedesktop.DBus.Properties", "Get",
        assocDefsInterface, assocDefsProperty);
}

void doIntrospect(boost::asio::io_context& io,
                  sdbusplus::asio::connection* systemBus,
                  const std::shared_ptr<InProgressIntrospect>& transaction,
                  InterfaceMapType& interfaceMap,
                  sdbusplus::asio::object_server& objectServer,
                  const std::string& path, int timeoutRetries = 0)
{
    constexpr int maxTimeoutRetries = 3;
    systemBus->async_method_call(
        [&io, &interfaceMap, &objectServer, transaction, path, systemBus,
         timeoutRetries](const boost::system::error_code ec,
                         const std::string& introspectXml) {
        if (ec)
        {
            if (ec.value() == boost::system::errc::timed_out &&
                timeoutRetries < maxTimeoutRetries)
            {
                doIntrospect(io, systemBus, transaction, interfaceMap,
                             objectServer, path, timeoutRetries + 1);
                return;
            }
            std::cerr << "Introspect call failed with error: " << ec << ", "
                      << ec.message()
                      << " on process: " << transaction->processName
                      << " path: " << path << "\n";
            return;
        }

        tinyxml2::XMLDocument doc;

        tinyxml2::XMLError e = doc.Parse(introspectXml.c_str());
        if (e != tinyxml2::XMLError::XML_SUCCESS)
        {
            std::cerr << "XML parsing failed\n";
            return;
        }

        tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
        if (pRoot == nullptr)
        {
            std::cerr << "XML document did not contain any data\n";
            return;
        }
        auto& thisPathMap = interfaceMap[path];
        tinyxml2::XMLElement* pElement = pRoot->FirstChildElement("interface");
        while (pElement != nullptr)
        {
            const char* ifaceName = pElement->Attribute("name");
            if (ifaceName == nullptr)
            {
                continue;
            }

            thisPathMap[transaction->processName].emplace(ifaceName);

            if (std::strcmp(ifaceName, assocDefsInterface) == 0)
            {
                doAssociations(io, systemBus, interfaceMap, objectServer,
                               transaction->processName, path);
            }

            pElement = pElement->NextSiblingElement("interface");
        }

        // Check if this new path has a pending association that can
        // now be completed.
        checkIfPendingAssociation(io, path, interfaceMap,
                                  transaction->assocMaps, objectServer);

        pElement = pRoot->FirstChildElement("node");
        while (pElement != nullptr)
        {
            const char* childPath = pElement->Attribute("name");
            if (childPath != nullptr)
            {
                std::string parentPath(path);
                if (parentPath == "/")
                {
                    parentPath.clear();
                }

                doIntrospect(io, systemBus, transaction, interfaceMap,
                             objectServer, parentPath + "/" + childPath);
            }
            pElement = pElement->NextSiblingElement("node");
        }
        },
        transaction->processName, path, "org.freedesktop.DBus.Introspectable",
        "Introspect");
}

void startNewIntrospect(
    sdbusplus::asio::connection* systemBus, boost::asio::io_context& io,
    InterfaceMapType& interfaceMap, const std::string& processName,
    AssociationMaps& assocMaps,
#ifdef MAPPER_ENABLE_DEBUG
    std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
        globalStartTime,
#endif
    sdbusplus::asio::object_server& objectServer)
{
    if (needToIntrospect(processName))
    {
        std::shared_ptr<InProgressIntrospect> transaction =
            std::make_shared<InProgressIntrospect>(systemBus, io, processName,
                                                   assocMaps
#ifdef MAPPER_ENABLE_DEBUG
                                                   ,
                                                   globalStartTime
#endif
            );

        doIntrospect(io, systemBus, transaction, interfaceMap, objectServer,
                     "/");
    }
}

void doListNames(
    boost::asio::io_context& io, InterfaceMapType& interfaceMap,
    sdbusplus::asio::connection* systemBus,
    boost::container::flat_map<std::string, std::string>& nameOwners,
    AssociationMaps& assocMaps, sdbusplus::asio::object_server& objectServer)
{
    systemBus->async_method_call(
        [&io, &interfaceMap, &nameOwners, &objectServer, systemBus,
         &assocMaps](const boost::system::error_code ec,
                     std::vector<std::string> processNames) {
        if (ec)
        {
            std::cerr << "Error getting names: " << ec << "\n";
            std::exit(EXIT_FAILURE);
            return;
        }
        // Try to make startup consistent
        std::sort(processNames.begin(), processNames.end());
#ifdef MAPPER_ENABLE_DEBUG
        std::shared_ptr<std::chrono::time_point<std::chrono::steady_clock>>
            globalStartTime = std::make_shared<
                std::chrono::time_point<std::chrono::steady_clock>>(
                std::chrono::steady_clock::now());
#endif
        for (const std::string& processName : processNames)
        {
            if (needToIntrospect(processName))
            {
                startNewIntrospect(systemBus, io, interfaceMap, processName,
                                   assocMaps,
#ifdef MAPPER_ENABLE_DEBUG
                                   globalStartTime,
#endif
                                   objectServer);
                updateOwners(systemBus, nameOwners, processName);
            }
        }
        },
        "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
        "ListNames");
}

// Remove parents of the passed in path that:
// 1) Only have the 3 default interfaces on them
//    - Means D-Bus created these, not application code,
//      with the Properties, Introspectable, and Peer ifaces
// 2) Have no other child for this owner
void removeUnneededParents(const std::string& objectPath,
                           const std::string& owner,
                           InterfaceMapType& interfaceMap)
{
    auto parent = objectPath;

    while (true)
    {
        auto pos = parent.find_last_of('/');
        if ((pos == std::string::npos) || (pos == 0))
        {
            break;
        }
        parent = parent.substr(0, pos);

        auto parentIt = interfaceMap.find(parent);
        if (parentIt == interfaceMap.end())
        {
            break;
        }

        auto ifacesIt = parentIt->second.find(owner);
        if (ifacesIt == parentIt->second.end())
        {
            break;
        }

        if (ifacesIt->second.size() != 3)
        {
            break;
        }

        auto childPath = parent + '/';

        // Remove this parent if there isn't a remaining child on this owner
        auto child = std::find_if(interfaceMap.begin(), interfaceMap.end(),
                                  [&owner, &childPath](const auto& entry) {
            return entry.first.starts_with(childPath) &&
                   (entry.second.find(owner) != entry.second.end());
        });

        if (child == interfaceMap.end())
        {
            parentIt->second.erase(ifacesIt);
            if (parentIt->second.empty())
            {
                interfaceMap.erase(parentIt);
            }
        }
        else
        {
            break;
        }
    }
}

int main()
{
    boost::asio::io_context io;
    std::shared_ptr<sdbusplus::asio::connection> systemBus =
        std::make_shared<sdbusplus::asio::connection>(io);

    sdbusplus::asio::object_server server(systemBus);

    // Construct a signal set registered for process termination.
    boost::asio::signal_set signals(io, SIGINT, SIGTERM);
    signals.async_wait(
        [&io](const boost::system::error_code&, int) { io.stop(); });

    InterfaceMapType interfaceMap;
    boost::container::flat_map<std::string, std::string> nameOwners;

    auto nameChangeHandler = [&interfaceMap, &io, &nameOwners, &server,
                              systemBus](sdbusplus::message_t& message) {
        std::string name;     // well-known
        std::string oldOwner; // unique-name
        std::string newOwner; // unique-name

        message.read(name, oldOwner, newOwner);

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

        if (!oldOwner.empty())
        {
            processNameChangeDelete(io, nameOwners, name, oldOwner,
                                    interfaceMap, associationMaps, server);
        }

        if (!newOwner.empty())
        {
#ifdef MAPPER_ENABLE_DEBUG
            auto transaction = std::make_shared<
                std::chrono::time_point<std::chrono::steady_clock>>(
                std::chrono::steady_clock::now());
#endif
            // New daemon added
            if (needToIntrospect(name))
            {
                nameOwners[newOwner] = name;
                startNewIntrospect(systemBus.get(), io, interfaceMap, name,
                                   associationMaps,
#ifdef MAPPER_ENABLE_DEBUG
                                   transaction,
#endif
                                   server);
            }
        }
    };

    sdbusplus::bus::match_t nameOwnerChanged(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::nameOwnerChanged(),
        std::move(nameChangeHandler));

    auto interfacesAddedHandler = [&io, &interfaceMap, &nameOwners,
                                   &server](sdbusplus::message_t& message) {
        sdbusplus::message::object_path objPath;
        InterfacesAdded interfacesAdded;
        message.read(objPath, interfacesAdded);
        std::string wellKnown;
        if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
        {
            return; // only introspect well-known
        }
        if (needToIntrospect(wellKnown))
        {
            processInterfaceAdded(io, interfaceMap, objPath, interfacesAdded,
                                  wellKnown, associationMaps, server);
        }
    };

    sdbusplus::bus::match_t interfacesAdded(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::interfacesAdded(),
        std::move(interfacesAddedHandler));

    auto interfacesRemovedHandler = [&io, &interfaceMap, &nameOwners,
                                     &server](sdbusplus::message_t& message) {
        sdbusplus::message::object_path objPath;
        std::vector<std::string> interfacesRemoved;
        message.read(objPath, interfacesRemoved);
        auto connectionMap = interfaceMap.find(objPath.str);
        if (connectionMap == interfaceMap.end())
        {
            return;
        }

        std::string sender;
        if (!getWellKnown(nameOwners, message.get_sender(), sender))
        {
            return;
        }
        for (const std::string& interface : interfacesRemoved)
        {
            auto interfaceSet = connectionMap->second.find(sender);
            if (interfaceSet == connectionMap->second.end())
            {
                continue;
            }

            if (interface == assocDefsInterface)
            {
                removeAssociation(io, objPath.str, sender, server,
                                  associationMaps);
            }

            interfaceSet->second.erase(interface);

            if (interfaceSet->second.empty())
            {
                // If this was the last interface on this connection,
                // erase the connection
                connectionMap->second.erase(interfaceSet);

                // Instead of checking if every single path is the endpoint
                // of an association that needs to be moved to pending,
                // only check when the only remaining owner of this path is
                // ourself, which would be because we still own the
                // association path.
                if ((connectionMap->second.size() == 1) &&
                    (connectionMap->second.begin()->first ==
                     "xyz.openbmc_project.ObjectMapper"))
                {
                    // Remove the 2 association D-Bus paths and move the
                    // association to pending.
                    moveAssociationToPending(io, objPath.str, associationMaps,
                                             server);
                }
            }
        }
        // If this was the last connection on this object path,
        // erase the object path
        if (connectionMap->second.empty())
        {
            interfaceMap.erase(connectionMap);
        }

        removeUnneededParents(objPath.str, sender, interfaceMap);
    };

    sdbusplus::bus::match_t interfacesRemoved(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::interfacesRemoved(),
        std::move(interfacesRemovedHandler));

    auto associationChangedHandler = [&io, &server, &nameOwners, &interfaceMap](
                                         sdbusplus::message_t& message) {
        std::string objectName;
        boost::container::flat_map<std::string,
                                   std::variant<std::vector<Association>>>
            values;
        message.read(objectName, values);
        auto prop = values.find(assocDefsProperty);
        if (prop != values.end())
        {
            std::vector<Association> associations =
                std::get<std::vector<Association>>(prop->second);

            std::string wellKnown;
            if (!getWellKnown(nameOwners, message.get_sender(), wellKnown))
            {
                return;
            }
            associationChanged(io, server, associations, message.get_path(),
                               wellKnown, interfaceMap, associationMaps);
        }
    };
    sdbusplus::bus::match_t assocChangedMatch(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        sdbusplus::bus::match::rules::interface(
            "org.freedesktop.DBus.Properties") +
            sdbusplus::bus::match::rules::member("PropertiesChanged") +
            sdbusplus::bus::match::rules::argN(0, assocDefsInterface),
        std::move(associationChangedHandler));

    std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
        server.add_interface("/xyz/openbmc_project/object_mapper",
                             "xyz.openbmc_project.ObjectMapper");

    iface->register_method(
        "GetAncestors", [&interfaceMap](std::string& reqPath,
                                        std::vector<std::string>& interfaces) {
            return getAncestors(interfaceMap, reqPath, interfaces);
        });

    iface->register_method(
        "GetObject", [&interfaceMap](const std::string& path,
                                     std::vector<std::string>& interfaces) {
            return getObject(interfaceMap, path, interfaces);
        });

    iface->register_method(
        "GetSubTree", [&interfaceMap](std::string& reqPath, int32_t depth,
                                      std::vector<std::string>& interfaces) {
            return getSubTree(interfaceMap, reqPath, depth, interfaces);
        });

    iface->register_method(
        "GetSubTreePaths",
        [&interfaceMap](std::string& reqPath, int32_t depth,
                        std::vector<std::string>& interfaces) {
        return getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
        });

    iface->register_method(
        "GetAssociatedSubTree",
        [&interfaceMap](const sdbusplus::message::object_path& associationPath,
                        const sdbusplus::message::object_path& reqPath,
                        int32_t depth, std::vector<std::string>& interfaces) {
        return getAssociatedSubTree(interfaceMap, associationMaps,
                                    associationPath, reqPath, depth,
                                    interfaces);
        });

    iface->register_method(
        "GetAssociatedSubTreePaths",
        [&interfaceMap](const sdbusplus::message::object_path& associationPath,
                        const sdbusplus::message::object_path& reqPath,
                        int32_t depth, std::vector<std::string>& interfaces) {
        return getAssociatedSubTreePaths(interfaceMap, associationMaps,
                                         associationPath, reqPath, depth,
                                         interfaces);
        });

    iface->initialize();

    io.post([&]() {
        doListNames(io, interfaceMap, systemBus.get(), nameOwners,
                    associationMaps, server);
    });

    systemBus->request_name("xyz.openbmc_project.ObjectMapper");

    io.run();
}
