#include <maps/wikimap/mapspro/libs/revision_meta/impl/blocking_commits_impl.h>

#include <algorithm>

namespace maps::wiki::revision_meta::impl {

namespace {

TCommitIds
intersection(const TCommitIds& lhs, const TCommitIds& rhs) {
    TCommitIds result;
    std::set_intersection(
        lhs.cbegin(), lhs.cend(),
        rhs.cbegin(), rhs.cend(),
        std::inserter(result, result.end())
    );
    return result;
}

} // namespace

Graph<TCommitId>::Components
getAllComponents(const TCommitIds& preApprovedCommits, const Relations& relations)
{
    Graph<TCommitId> graph;

    for (const auto commitId: preApprovedCommits) {
        graph.addVertex(commitId);
    }

    for (const auto relation: relations) {
        graph.addEdge(relation.commitId, relation.relatesTo);
    }

    return graph.components();
}

Graph<TCommitId>::Component
getComponent(const Graph<TCommitId>::Components& components, TCommitId commitId)
{
    for (const auto& component: components) {
        if (component.count(commitId)) {
            return component;
        }
    }

    return {};
}

TCommitIds
getBlockingCommits(
    TCommitId commitId,
    const TCommitIds& preApprovedCommits,
    const Relations& relations,
    const TCommitIds& commitIdsWithActiveTasks)
{
    auto result = intersection(
        getComponent(
            getAllComponents(preApprovedCommits, relations),
            commitId
        ),
        commitIdsWithActiveTasks
    );
    result.erase(commitId);
    return result;
}

TCommitIds
getCommitsReadyForApprove(
    const TCommitIds& preApprovedCommits,
    const Relations& relations,
    const TCommitIds& commitIdsWithActiveTasks)
{
    const auto components = getAllComponents(preApprovedCommits, relations);

    TCommitIds result;
    for (const auto& component: components) {
        if (intersection(component, commitIdsWithActiveTasks).empty()) {
            result.insert(component.cbegin(), component.cend());
        }
    }
    return result;
}

} // namespace maps::wiki::revision_meta::impl
