#include "handler.hpp"

#include "types.hpp"

#include <xyz/openbmc_project/Common/error.hpp>

#include <algorithm>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
                        const std::string& objectPath,
                        const ConnectionNames::value_type& interfaceMap)
{
    // Adds an object path/service name/interface list entry to
    // the results of GetSubTree and GetAncestors.
    // If an entry for the object path already exists, just add the
    // service name and interfaces to that entry, otherwise create
    // a new entry.
    auto entry = std::find_if(objectMap.begin(), objectMap.end(),
                              [&objectPath](const auto& i) {
        return objectPath == i.first;
    });

    if (entry != objectMap.end())
    {
        entry->second.emplace(interfaceMap);
    }
    else
    {
        InterfaceMapType::value_type object;
        object.first = objectPath;
        object.second.emplace(interfaceMap);
        objectMap.push_back(object);
    }
}

std::vector<InterfaceMapType::value_type>
    getAncestors(const InterfaceMapType& interfaceMap, std::string reqPath,
                 std::vector<std::string>& interfaces)
{
    // Interfaces need to be sorted for intersect to function
    std::sort(interfaces.begin(), interfaces.end());

    if (reqPath.ends_with("/"))
    {
        reqPath.pop_back();
    }
    if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::
            ResourceNotFound();
    }

    std::vector<InterfaceMapType::value_type> ret;
    for (const auto& objectPath : interfaceMap)
    {
        const auto& thisPath = objectPath.first;

        if (reqPath == thisPath)
        {
            continue;
        }

        if (reqPath.starts_with(thisPath))
        {
            if (interfaces.empty())
            {
                ret.emplace_back(objectPath);
            }
            else
            {
                for (const auto& interfaceMap : objectPath.second)
                {
                    std::vector<std::string> output(std::min(
                        interfaces.size(), interfaceMap.second.size()));
                    // Return iterator points at the first output elemtn,
                    // meaning that there are no intersections.
                    if (std::set_intersection(interfaces.begin(),
                                              interfaces.end(),
                                              interfaceMap.second.begin(),
                                              interfaceMap.second.end(),
                                              output.begin()) != output.begin())
                    {
                        addObjectMapResult(ret, thisPath, interfaceMap);
                    }
                }
            }
        }
    }

    return ret;
}

ConnectionNames getObject(const InterfaceMapType& interfaceMap,
                          const std::string& path,
                          std::vector<std::string>& interfaces)
{
    ConnectionNames results;

    // Interfaces need to be sorted for intersect to function
    std::sort(interfaces.begin(), interfaces.end());
    auto pathRef = interfaceMap.find(path);
    if (pathRef == interfaceMap.end())
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::
            ResourceNotFound();
    }
    if (interfaces.empty())
    {
        return pathRef->second;
    }
    for (const auto& interfaceMap : pathRef->second)
    {
        std::vector<std::string> output(
            std::min(interfaces.size(), interfaceMap.second.size()));
        // Return iterator points at the first output elemtn,
        // meaning that there are no intersections.
        if (std::set_intersection(interfaces.begin(), interfaces.end(),
                                  interfaceMap.second.begin(),
                                  interfaceMap.second.end(),
                                  output.begin()) != output.begin())
        {
            results.emplace(interfaceMap.first, interfaceMap.second);
        }
    }

    if (results.empty())
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::
            ResourceNotFound();
    }

    return results;
}

std::vector<InterfaceMapType::value_type>
    getSubTree(const InterfaceMapType& interfaceMap, std::string reqPath,
               int32_t depth, std::vector<std::string>& interfaces)
{
    if (depth <= 0)
    {
        depth = std::numeric_limits<int32_t>::max();
    }
    // Interfaces need to be sorted for intersect to function
    std::sort(interfaces.begin(), interfaces.end());

    // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
    // will be guaranteed not to have a trailing "/"
    if (!reqPath.ends_with("/"))
    {
        reqPath += "/";
    }
    std::string_view reqPathStripped =
        std::string_view(reqPath).substr(0, reqPath.size() - 1);

    if (!reqPathStripped.empty() &&
        interfaceMap.find(reqPathStripped) == interfaceMap.end())
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::
            ResourceNotFound();
    }

    std::vector<InterfaceMapType::value_type> ret;
    for (const auto& objectPath : interfaceMap)
    {
        const auto& thisPath = objectPath.first;

        // Skip exact match on stripped search term
        if (thisPath == reqPathStripped)
        {
            continue;
        }

        if (thisPath.starts_with(reqPath))
        {
            // count the number of slashes past the stripped search term
            int32_t thisDepth = std::count(
                thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
            if (thisDepth <= depth)
            {
                for (const auto& interfaceMap : objectPath.second)
                {
                    std::vector<std::string> output(std::min(
                        interfaces.size(), interfaceMap.second.size()));
                    // Return iterator points at the first output elemtn,
                    // meaning that there are no intersections.
                    if (std::set_intersection(
                            interfaces.begin(), interfaces.end(),
                            interfaceMap.second.begin(),
                            interfaceMap.second.end(),
                            output.begin()) != output.begin() ||
                        interfaces.empty())
                    {
                        addObjectMapResult(ret, thisPath, interfaceMap);
                    }
                }
            }
        }
    }

    return ret;
}

std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
                                         std::string reqPath, int32_t depth,
                                         std::vector<std::string>& interfaces)
{
    if (depth <= 0)
    {
        depth = std::numeric_limits<int32_t>::max();
    }
    // Interfaces need to be sorted for intersect to function
    std::sort(interfaces.begin(), interfaces.end());

    // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
    // will be guaranteed not to have a trailing "/"
    if (!reqPath.ends_with("/"))
    {
        reqPath += "/";
    }
    std::string_view reqPathStripped =
        std::string_view(reqPath).substr(0, reqPath.size() - 1);

    if (!reqPathStripped.empty() &&
        interfaceMap.find(reqPathStripped) == interfaceMap.end())
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::
            ResourceNotFound();
    }

    std::vector<std::string> ret;
    for (const auto& objectPath : interfaceMap)
    {
        const auto& thisPath = objectPath.first;

        // Skip exact match on stripped search term
        if (thisPath == reqPathStripped)
        {
            continue;
        }

        if (thisPath.starts_with(reqPath))
        {
            // count the number of slashes past the stripped search term
            int thisDepth = std::count(
                thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
            if (thisDepth <= depth)
            {
                bool add = interfaces.empty();
                for (const auto& interfaceMap : objectPath.second)
                {
                    std::vector<std::string> output(std::min(
                        interfaces.size(), interfaceMap.second.size()));
                    // Return iterator points at the first output elemtn,
                    // meaning that there are no intersections.
                    if (std::set_intersection(interfaces.begin(),
                                              interfaces.end(),
                                              interfaceMap.second.begin(),
                                              interfaceMap.second.end(),
                                              output.begin()) != output.begin())
                    {
                        add = true;
                        break;
                    }
                }
                if (add)
                {
                    // TODO(ed) this is a copy
                    ret.emplace_back(thisPath);
                }
            }
        }
    }

    return ret;
}

std::vector<InterfaceMapType::value_type>
    getAssociatedSubTree(const InterfaceMapType& interfaceMap,
                         const AssociationMaps& associationMaps,
                         const sdbusplus::message::object_path& associationPath,
                         const sdbusplus::message::object_path& reqPath,
                         int32_t depth, std::vector<std::string>& interfaces)
{
    auto findEndpoint = associationMaps.ifaces.find(associationPath.str);
    if (findEndpoint == associationMaps.ifaces.end())
    {
        return {};
    }
    const std::vector<std::string>& association =
        std::get<endpointsPos>(findEndpoint->second);
    std::unordered_set<std::string> associationSet(association.begin(),
                                                   association.end());
    const std::vector<InterfaceMapType::value_type>& interfacePairs =
        getSubTree(interfaceMap, reqPath, depth, interfaces);

    std::vector<InterfaceMapType::value_type> output;
    for (const InterfaceMapType::value_type& interfacePair : interfacePairs)
    {
        if (associationSet.contains(interfacePair.first))
        {
            output.emplace_back(interfacePair);
        }
    }
    return output;
}

std::vector<std::string> getAssociatedSubTreePaths(
    const InterfaceMapType& interfaceMap,
    const AssociationMaps& associationMaps,
    const sdbusplus::message::object_path& associationPath,
    const sdbusplus::message::object_path& reqPath, int32_t depth,
    std::vector<std::string>& interfaces)
{
    auto findEndpoint = associationMaps.ifaces.find(associationPath.str);
    if (findEndpoint == associationMaps.ifaces.end())
    {
        return {};
    }
    const std::vector<std::string>& association =
        std::get<endpointsPos>(findEndpoint->second);
    std::unordered_set<std::string> associationSet(association.begin(),
                                                   association.end());
    const std::vector<std::string>& paths =
        getSubTreePaths(interfaceMap, reqPath, depth, interfaces);

    std::vector<std::string> output;
    for (const auto& path : paths)
    {
        if (associationSet.contains(path))
        {
            output.emplace_back(path);
        }
    }
    return output;
}
