#pragma once

#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/frame.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 Device: Table<db::eye::Device> {
    static constexpr std::string_view name_{"eye.device"sv};

    static constexpr BigSerialKey id{"device_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr JsonColumn attrs{"attrs"sv, name_};

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

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

    static constexpr BigSerialKey id{"frame_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr NumericColumn<TId> deviceId{"device_id"sv, name_};
    static constexpr BooleanColumn deleted{"deleted"sv, name_};
    static constexpr NumericColumn<int16_t> orientation{"orientation"sv, name_};
    static constexpr JsonColumn urlContext{"url_context"sv, name_};
    static constexpr NumericColumn<int16_t> width{"width"sv, name_};
    static constexpr NumericColumn<int16_t> height{"height"sv, name_};
    static constexpr TimePointColumn time{"time"sv, name_};

    static constexpr auto columns_() {
        return std::tie(id, txnId, deviceId, deleted, orientation, urlContext, width, height, time);
    }
};

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

    static constexpr Int64PrimaryKey frameId{"frame_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 Nullable<NumericArrayColumn<double>> move{"move"sv, name_};

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

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

    static constexpr Int64PrimaryKey frameId{"frame_id"sv, name_};
    static constexpr NumericColumn<TId> txnId{"txn_id"sv, name_};
    static constexpr EnumColumn<FeaturePrivacy> type{"type"sv, name_};

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

} // namespace table

using DeviceGateway = db::TxnIdGatewayBase<table::Device>;
using FrameGateway = db::TxnIdGatewayBase<table::Frame>;
using FrameLocationGateway = db::TxnIdGatewayBase<table::FrameLocation>;
using FramePrivacyGateway = db::TxnIdGatewayBase<table::FramePrivacy>;

} // namespace eye

TABLE_TRAITS(eye::Device, eye::table::Device);
TABLE_TRAITS(eye::Frame, eye::table::Frame);
TABLE_TRAITS(eye::FrameLocation, eye::table::FrameLocation);
TABLE_TRAITS(eye::FramePrivacy, eye::table::FramePrivacy);

} // namespace maps::mrc::db
