#pragma once

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

#include <maps/libs/sql_chemistry/include/columns/array.h>

namespace maps::mrc::db {
namespace eye {
namespace table {

using namespace sql_chemistry;

struct Object : Table<db::eye::Object> {
    static constexpr std::string_view name_{"eye.object"sv};

    static constexpr BigSerialKey id{"object_id"sv, name_};
    static constexpr NumericColumn<TId> primaryDetectionId{"primary_detection_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr BooleanColumn deleted{"deleted", name_};
    static constexpr EnumColumn<ObjectType> type{"type", name_};
    static constexpr JsonColumn attrs{"attrs"sv, name_};
    static constexpr NullableTimePointColumn disappearedAt{"disappeared_at"sv, name_};

    static constexpr auto columns_()
    {
        return std::tie(id, primaryDetectionId, txnId, deleted, type, attrs, disappearedAt);
    }
};

struct ObjectLocation: Table<db::eye::ObjectLocation> {
    static constexpr std::string_view name_{"eye.object_location"sv};
    static constexpr Int64PrimaryKey objectId{"object_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr MercatorColumn<geolib3::Point2> position{"position"sv, name_};
    static constexpr NumericArrayColumn<double> rotation{"rotation"sv, name_};

    static constexpr auto columns_() {
        return std::tie(objectId, txnId, position, rotation);
    }
};

struct PrimaryDetectionRelation: Table<db::eye::PrimaryDetectionRelation> {
    static constexpr std::string_view name_{"eye.primary_detection_relation"sv};
    static constexpr BigSerialKey relationId{"relation_id"sv, name_};
    static constexpr NumericColumn<TId> primaryDetectionId{"primary_detection_id"sv, name_};
    static constexpr NumericColumn<TId> detectionId{"detection_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr BooleanColumn deleted{"deleted"sv, name_};

    static constexpr auto columns_() {
        return std::tie(relationId, primaryDetectionId, detectionId, txnId, deleted);
    }
};

struct ObjectRelation: Table<db::eye::ObjectRelation> {
    static constexpr std::string_view name_{"eye.object_relation"sv};

    static constexpr BigSerialKey id{"relation_id"sv, name_};
    static constexpr NumericColumn<TId> masterObjectId{"master_object_id"sv, name_};
    static constexpr NumericColumn<TId> slaveObjectId{"slave_object_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr BooleanColumn deleted{"deleted"sv, name_};

    static constexpr auto columns_()
    {
        return std::tie(id, masterObjectId, slaveObjectId, txnId, deleted);
    }
};

struct ObjectMissingOnFrame: Table<db::eye::ObjectMissingOnFrame> {
    static constexpr std::string_view name_{"eye.object_missing_on_frame"sv};

    static constexpr BigSerialKey id{"id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr NumericColumn<TId> objectId{"object_id"sv, name_};
    static constexpr NumericColumn<TId> frameId{"frame_id"sv, name_};
    static constexpr BooleanColumn deleted{"deleted"sv, name_};

    static constexpr auto columns_()
    {
        return std::tie(id, txnId, objectId, frameId, deleted);
    }
};

} // namespace table

using ObjectGateway = db::TxnIdGatewayBase<table::Object>;
using ObjectLocationGateway = db::TxnIdGatewayBase<table::ObjectLocation>;
using PrimaryDetectionRelationGateway = db::TxnIdGatewayBase<table::PrimaryDetectionRelation>;
using ObjectRelationGateway = db::TxnIdGatewayBase<table::ObjectRelation>;
using ObjectMissingOnFrameGateway = db::TxnIdGatewayBase<table::ObjectMissingOnFrame>;

} // namespace eye

TABLE_TRAITS(eye::Object, eye::table::Object);
TABLE_TRAITS(eye::ObjectLocation, eye::table::ObjectLocation);
TABLE_TRAITS(eye::PrimaryDetectionRelation, eye::table::PrimaryDetectionRelation);
TABLE_TRAITS(eye::ObjectRelation, eye::table::ObjectRelation);
TABLE_TRAITS(eye::ObjectMissingOnFrameGateway, eye::table::ObjectMissingOnFrame);

} // namespace maps::mrc::db::eye
