#include "snapshot_impl.h"
#include "object_impl.h"

#include <yandex/maps/wiki/common/retry_duration.h>
#include <yandex/maps/wiki/revision/objectrevision.h>

namespace maps {
namespace wiki {
namespace diffalert {

LongtaskSnapshot::LongtaskSnapshot(Impl&& impl)
    : impl_(new Impl(std::move(impl)))
{ }

LongtaskSnapshot::LongtaskSnapshot(LongtaskSnapshot&&) noexcept = default;
LongtaskSnapshot& LongtaskSnapshot::operator=(LongtaskSnapshot&&) noexcept = default;
LongtaskSnapshot::~LongtaskSnapshot() = default;

std::vector<Snapshot::ObjectPtr> LongtaskSnapshot::objectsByIds(const TIds& ids)
{
    std::vector<ObjectPtr> objects;
    if (ids.empty()) {
        return objects;
    }

    auto revisions = common::retryDuration([&] {
        auto snapshot = impl_->revSnapshotFct().get();
        return snapshot->objectRevisions(ids);
    });

    objects.reserve(ids.size());
    for (const auto& [_, rev] : revisions) {
        if (rev.data().deleted ||
                rev.type() != revision::RevisionType::RegularObject) {
            continue;
        }
        objects.emplace_back(new LongtaskObject(
            LongtaskObject::Impl(rev, impl_->revSnapshotFct(), impl_->config())));
    }
    return objects;
}

std::vector<Snapshot::ObjectPtr> LongtaskSnapshot::primitivesByEnvelope(
        const Envelope& envelope,
        GeometryType geomType,
        const std::vector<std::string>& categoryIds)
{
    if (envelope.isNull()) {
        return {};
    }

    if (impl_->viewTxnFct().isAvailable()) {
        return impl_->primitivesByEnvelopeFromView(envelope, geomType, categoryIds);
    }
    return impl_->primitivesByEnvelopeFromRevision(envelope, geomType, categoryIds);
}

const GeomIndex& LongtaskSnapshot::bldWith3Dmodel() const {
    ASSERT(impl_->bldWith3Dmodel());
    return *(impl_->bldWith3Dmodel());
}

} // namespace diffalert
} // namespace wiki
} // namespace maps
