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