#include "handler.hpp"

#include "path.hpp"
#include "types.hpp"

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

#include <algorithm>
#include <iterator>
#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.contains(reqPath))
    {
        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& connectionInterfaces : objectPath.second)
                {
                    std::vector<std::string> output(std::min(
                        interfaces.size(), connectionInterfaces.second.size()));
                    // Return iterator points at the first output elemtn,
                    // meaning that there are no intersections.
                    if (std::set_intersection(
                            interfaces.begin(), interfaces.end(),
                            connectionInterfaces.second.begin(),
                            connectionInterfaces.second.end(),
                            output.begin()) != output.begin())
                    {
                        addObjectMapResult(ret, thisPath, connectionInterfaces);
                    }
                }
            }
        }
    }

    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& connectionInterfaces : pathRef->second)
    {
        std::vector<std::string> output(
            std::min(interfaces.size(), connectionInterfaces.second.size()));
        // Return iterator points at the first output elemtn,
        // meaning that there are no intersections.
        if (std::set_intersection(interfaces.begin(), interfaces.end(),
                                  connectionInterfaces.second.begin(),
                                  connectionInterfaces.second.end(),
                                  output.begin()) != output.begin())
        {
            results.emplace(connectionInterfaces.first,
                            connectionInterfaces.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
            auto thisDepth = std::count(
                thisPath.begin() + std::distance(reqPathStripped.begin(),
                                                 reqPathStripped.end()),
                thisPath.end(), '/');
            if (thisDepth <= depth)
            {
                for (const auto& connectionInterfaces : objectPath.second)
                {
                    std::vector<std::string> output(std::min(
                        interfaces.size(), connectionInterfaces.second.size()));
                    // Return iterator points at the first output elemtn,
                    // meaning that there are no intersections.
                    if (std::set_intersection(
                            interfaces.begin(), interfaces.end(),
                            connectionInterfaces.second.begin(),
                            connectionInterfaces.second.end(),
                            output.begin()) != output.begin() ||
                        interfaces.empty())
                    {
                        addObjectMapResult(ret, thisPath, connectionInterfaces);
                    }
                }
            }
        }
    }

    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
            auto thisDepth = std::count(
                thisPath.begin() + std::distance(reqPathStripped.begin(),
                                                 reqPathStripped.end()),
                thisPath.end(), '/');
            if (thisDepth <= depth)
            {
                bool add = interfaces.empty();
                for (const auto& connectionInterfaces : objectPath.second)
                {
                    std::vector<std::string> output(std::min(
                        interfaces.size(), connectionInterfaces.second.size()));
                    // Return iterator points at the first output elemtn,
                    // meaning that there are no intersections.
                    if (std::set_intersection(
                            interfaces.begin(), interfaces.end(),
                            connectionInterfaces.second.begin(),
                            connectionInterfaces.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;
}

// This function works like getSubTreePaths() but only matching id with
// the leaf-name instead of full path.
static std::vector<std::string> getSubTreePathsById(
    const InterfaceMapType& interfaceMap, const std::string& id,
    const std::string& objectPath, std::vector<std::string>& interfaces)
{
    std::sort(interfaces.begin(), interfaces.end());

    std::string localObjectPath = objectPath;

    if (!localObjectPath.ends_with("/"))
    {
        localObjectPath += "/";
    }
    std::string_view objectPathStripped =
        std::string_view(localObjectPath).substr(0, localObjectPath.size() - 1);

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

    bool validId = false;
    std::vector<std::string> output;
    for (const auto& path : interfaceMap)
    {
        const auto& thisPath = path.first;

        // Skip the path does not end with the id
        if (!thisPath.ends_with("/" + id))
        {
            continue;
        }

        // Valid if id is matching
        validId = true;

        // Skip exact match on stripped search term
        if (thisPath == objectPathStripped)
        {
            continue;
        }
        if (thisPath.starts_with(objectPath))
        {
            for (const auto& connectionInterfaces : path.second)
            {
                std::vector<std::string> tempoutput(std::min(
                    interfaces.size(), connectionInterfaces.second.size()));
                if (std::set_intersection(interfaces.begin(), interfaces.end(),
                                          connectionInterfaces.second.begin(),
                                          connectionInterfaces.second.end(),
                                          tempoutput.begin()) !=
                    tempoutput.begin())
                {
                    output.emplace_back(thisPath);
                    break;
                }
            }
        }
    }
    if (!validId)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::
            ResourceNotFound();
    }
    return output;
}

std::vector<InterfaceMapType::value_type> getAssociatedSubTreeById(
    const InterfaceMapType& interfaceMap,
    const AssociationMaps& associationMaps, const std::string& id,
    const std::string& objectPath, std::vector<std::string>& subtreeInterfaces,
    const std::string& association,
    std::vector<std::string>& endpointInterfaces)
{
    std::vector<std::string> subtreePaths =
        getSubTreePathsById(interfaceMap, id, objectPath, subtreeInterfaces);

    std::vector<InterfaceMapType::value_type> output;
    for (const auto& subtreePath : subtreePaths)
    {
        // Form the association path
        std::string associationPathStr =
            appendPathSegment(subtreePath, association);
        sdbusplus::message::object_path associationPath(associationPathStr);

        auto associatedSubTree =
            getAssociatedSubTree(interfaceMap, associationMaps, associationPath,
                                 objectPath, 0, endpointInterfaces);

        output.insert(output.end(), associatedSubTree.begin(),
                      associatedSubTree.end());
    }
    return output;
}

std::vector<std::string> getAssociatedSubTreePathsById(
    const InterfaceMapType& interfaceMap,
    const AssociationMaps& associationMaps, const std::string& id,
    const std::string& objectPath, std::vector<std::string>& subtreeInterfaces,
    const std::string& association,
    std::vector<std::string>& endpointInterfaces)
{
    std::vector<std::string> subtreePaths =
        getSubTreePathsById(interfaceMap, id, objectPath, subtreeInterfaces);
    std::vector<std::string> output;
    for (const auto& subtreePath : subtreePaths)
    {
        // Form the association path
        std::string associationPathStr =
            appendPathSegment(subtreePath, association);
        sdbusplus::message::object_path associationPath(associationPathStr);

        auto associatedSubTree = getAssociatedSubTreePaths(
            interfaceMap, associationMaps, associationPath, objectPath, 0,
            endpointInterfaces);

        output.insert(output.end(), associatedSubTree.begin(),
                      associatedSubTree.end());
    }

    return output;
}
