#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/hypothesis.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/object.h>
#include <maps/wikimap/mapspro/services/mrc/libs/object/include/loader.h>

#include <maps/wikimap/mapspro/services/mrc/eye/lib/generate_hypothesis/include/common.h>

namespace maps::mrc::eye::qa {

class ValidatorBase {
public:
    virtual ~ValidatorBase() = default;

    virtual bool appliesToObject(const db::eye::Object& object) const = 0;

    virtual db::eye::Hypotheses validate(
        const db::eye::Object& object,
        const db::eye::ObjectLocation& location,
        const db::eye::Objects& slaveObjects,
        object::Loader& loader) const = 0;
};

template<
    typename HypothesisGeneratorImpl,
    db::eye::ObjectType objectType>
class Validator : public ValidatorBase
{
public:

    Validator() = default;

    bool appliesToObject(const db::eye::Object& object) const override
    {
        return object.type() == objectType &&
            hypothesisGenerator_.appliesToObject(object);
    }

    db::eye::Hypotheses validate(
        const db::eye::Object& object,
        const db::eye::ObjectLocation& location,
        const db::eye::Objects& slaveObjects,
        object::Loader& loader) const override
    {
        return hypothesisGenerator_.validate(object, location, slaveObjects, loader);
    }

private:
    HypothesisGeneratorImpl hypothesisGenerator_;
};

using LoaderByObjectIdFactory = std::function<object::LoaderHolder(db::TId)>;

std::unordered_map<db::TId, db::eye::Hypotheses> validateInParallel(
    const ValidatorBase& validator,
    const ObjectsContext& objectsContext,
    LoaderByObjectIdFactory loaderFactory);


} // namespace maps::mrc::eye::qa
