#include <yandex/maps/wiki/revision/historical_snapshot.h>
#include <yandex/maps/wiki/revision/range_helpers.h>
#include "snapshots_impl.h"
#include "helpers.h"
#include <maps/libs/common/include/exception.h>

#include <utility>

namespace maps::wiki::revision {

using namespace helpers;

HistoricalSnapshot::HistoricalSnapshot(
        std::shared_ptr<HistoricalSnapshotImpl> impl)
    : impl_(std::move(impl))
{
    REQUIRE(impl_->minCommitId <= impl_->maxCommitId,
            "invalid interval: " <<
            impl_->minCommitId << "," << impl_->maxCommitId);
}

HistoricalSnapshot::~HistoricalSnapshot() = default;

Reader
HistoricalSnapshot::reader() const
{
    return Reader(impl_->reader);
}

DBID
HistoricalSnapshot::minCommitId() const
{
    return impl_->minCommitId;
}

DBID
HistoricalSnapshot::maxCommitId() const
{
    return impl_->maxCommitId;
}

RevisionIds
HistoricalSnapshot::revisionIdsByFilter(const filters::FilterExpr& expr) const
{
    if (impl_->maxCommitId == 0) {
        return {};
    }

    auto boundedFilter =
        filters::CommitAttr::id() >= impl_->minCommitId &&
        filters::ObjRevAttr::commitId() >= impl_->minCommitId &&
        filters::CommitAttr::id() <= impl_->maxCommitId &&
        filters::ObjRevAttr::commitId() <= impl_->maxCommitId &&
        filters::ProxyReferenceFilterExpr(expr);

    return impl_->reader->loadRevisionIds(
        LoadLimitations::Branch,
        NO_SNAPSHOT_ID,
        NO_LIMIT,
        boundedFilter
    );
}

Revisions
HistoricalSnapshot::relationsByFilter(const filters::FilterExpr& expr) const
{
    if (impl_->maxCommitId == 0) {
        return {};
    }

    auto boundedFilter = (
        filters::CommitAttr::id() >= impl_->minCommitId &&
        filters::ObjRevAttr::commitId() >= impl_->minCommitId &&
        filters::CommitAttr::id() <= impl_->maxCommitId &&
        filters::ObjRevAttr::commitId() <= impl_->maxCommitId &&
        filters::ObjRevAttr::isRelation() &&
        filters::ProxyReferenceFilterExpr(expr)
    );

    return impl_->reader->loadRevisions(
        LoadLimitations::Branch,
        NO_SNAPSHOT_ID,
        NO_LIMIT,
        boundedFilter
    );
}

RevisionIds
HistoricalSnapshot::revisionIdsByFilter(const ConstRange<DBID>& objectIds,
    const filters::FilterExpr& expr) const
{
    if (impl_->maxCommitId == 0) {
        return {};
    }

    auto boundedFilter =
        filters::CommitAttr::id() >= impl_->minCommitId &&
        filters::ObjRevAttr::commitId() >= impl_->minCommitId &&
        filters::CommitAttr::id() <= impl_->maxCommitId &&
        filters::ObjRevAttr::commitId() <= impl_->maxCommitId &&
        filters::ProxyReferenceFilterExpr(expr);

    return impl_->reader->loadRevisionIds(
        LoadLimitations::Branch,
        NO_SNAPSHOT_ID,
        NO_LIMIT,
        idsToSet(objectIds),
        boundedFilter
    );
}

} // namespace maps::wiki::revision
