#pragma once

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

namespace maps::mrc::eye {

class HypothesisContext {
public:
    struct Item {
        Item(
            const db::eye::Object& object,
            const db::eye::ObjectLocation& objectLocation,
            const db::eye::Detection& detection,
            const db::eye::DetectionGroup& detectionGroup,
            const db::eye::Frame& frame,
            const db::eye::FrameLocation& frameLocation,
            const db::eye::FramePrivacy& framePrivacy);

        db::eye::Object object;
        db::eye::ObjectLocation objectLocation;
        db::eye::Detection detection;
        db::eye::DetectionGroup detectionGroup;
        db::eye::Frame frame;
        db::eye::FrameLocation frameLocation;
        db::eye::FramePrivacy framePrivacy;

        bool isPrimary() const;
    };
    using Items = std::vector<Item>;

public:
    HypothesisContext(const Items& items);

    const Items& items() const;
    const Item& primaryItem() const;

    size_t size() const;
    bool empty() const;

    Items getItemsToApprove() const;

private:
    Items items_;
};

class HypothesisStore {

public:
    HypothesisStore() = default;

    // Load context for given hypotheses.
    // Use only not deleted hypotheses.
    // Context does not contain infomation with
    // deleted object, detection, relations and frames
    static HypothesisStore fromHypotheses(
        pqxx::transaction_base& txn,
        const db::eye::Hypotheses& hypotheses);

    auto begin() const { return range_.cbegin(); }
    auto end() const { return range_.cend(); }

    // Return count of hypotheses with loaded context
    size_t size() const { return range_.size(); };

private:
    HypothesisStore(
        db::IdTo<db::eye::Hypothesis> hypothesisById,
        db::IdTo<db::TIds> objectIdsByHypothesisId,
        db::IdTo<db::eye::Object> objectById,
        db::IdTo<db::eye::ObjectLocation> objectLocationByObjectId,
        db::IdTo<db::TIds> detectionIdsByPrimaryDetectionId,
        db::IdTo<db::eye::Detection> detectionById,
        db::IdTo<db::eye::DetectionGroup> groupById,
        db::IdTo<db::eye::Frame> frameById,
        db::IdTo<db::eye::FrameLocation> frameLocationByFrameId,
        db::IdTo<db::eye::FramePrivacy> framePrivacyByFrameId);

    std::vector<std::pair<db::eye::Hypothesis, HypothesisContext>> range_;
};

} // namespace maps::mrc::eye
