#pragma once

#include "common.h"

#include <maps/wikimap/mapspro/services/mrc/libs/common/include/image_box.h>

#include <maps/libs/sql_chemistry/include/gateway_access.h>

#include <maps/libs/enum_io/include/enum_io_fwd.h>
#include <maps/libs/introspection/include/comparison.h>
#include <maps/libs/introspection/include/stream_output.h>

namespace maps::mrc::db {

enum class ObjectInPhotoType {
    Face = 1,
    LicensePlate = 2
};

DECLARE_ENUM_IO(ObjectInPhotoType);

class ObjectInPhoto {
public:
    ObjectInPhoto(TId featureId, ObjectInPhotoType type,
            int32_t minX, int32_t minY, int32_t maxX, int32_t maxY,
            float confidence)
        : id_{}
        , featureId_(featureId)
        , type_(type)
        , minX_(minX)
        , minY_(minY)
        , maxX_(maxX)
        , maxY_(maxY)
        , confidence_(confidence)
    {}

    ObjectInPhoto(
            TId featureId,
            ObjectInPhotoType type,
            const common::ImageBox& box,
            float confidence)
        : ObjectInPhoto(featureId, type, box.minX(), box.minY(), box.maxX(), box.maxY(), confidence)
    {}

    TId id() const { return id_; }

    TId featureId() const { return featureId_; }

    ObjectInPhotoType type() const { return type_; }

    int32_t minX() const { return minX_; }

    int32_t minY() const { return minY_; }

    int32_t maxX() const { return maxX_; }

    int32_t maxY() const { return maxY_; }

    common::ImageBox imageBox() const { return common::ImageBox(minX_, minY_, maxX_, maxY_); }

    float confidence() const { return confidence_; }

private:
    friend class sql_chemistry::GatewayAccess<ObjectInPhoto>;

    ObjectInPhoto() = default;

    template <typename T>
    static auto introspect(T& t) {
        return std::tie(t.id_, t.featureId_, t.type_, t.minX_, t.minY_,
            t.maxX_, t.maxY_, t.confidence_);
    }

    TId id_;
    TId featureId_;
    ObjectInPhotoType type_;
    int32_t minX_{}, minY_{}, maxX_{}, maxY_{};
    float confidence_;

public:
    auto introspect() const { return introspect(*this); }
};

using ObjectsInPhoto = std::vector<ObjectInPhoto>;

} // namespace maps::mrc::db
