#pragma once

#include "eye_panorama.h"

#include <maps/libs/geolib/include/heading.h>
#include <maps/libs/sql_chemistry/include/gateway_access.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/types.h>

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

class PanoramaSessionToDevice {
public:
    PanoramaSessionToDevice(
        std::uint64_t sessionId, TId deviceId, geolib3::Degrees deviation)
        : sessionId_{sessionId}
        , deviceId_{deviceId}
        , deviation_{static_cast<float>(deviation.value())}
    { }

    std::uint64_t sessionId() const { return sessionId_; }

    TId deviceId() const { return deviceId_; }

    // CW deviation from panorama vehicle course.
    geolib3::Degrees deviation() const { return geolib3::Degrees{deviation_}; }

private:
    PanoramaSessionToDevice() = default;

    friend class sql_chemistry::GatewayAccess<PanoramaSessionToDevice>;

    template<typename T>
    static auto introspect(T& t)
    {
        return std::tie(t.sessionId_, t.deviceId_, t.deviation_);
    }

    std::uint64_t sessionId_{0};
    TId deviceId_{0};
    float deviation_{.0f};

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

using PanoramaSessionToDevices = std::vector<PanoramaSessionToDevice>;

class PanoramaToFrame {
public:
    PanoramaToFrame(
        const PanoramaOID& oid,
        TId frameId,
        const geolib3::Heading& heading,
        const geolib3::Degrees& tilt,
        const geolib3::Degrees& horizontalFOV,
        const common::Size& size)
        : oid_{oid}
        , frameId_{frameId}
        , heading_{heading.value()}
        , tilt_{tilt.value()}
        , horizontalFOV_{horizontalFOV.value()}
        , width_{static_cast<std::uint16_t>(size.width)}
        , height_{static_cast<std::uint16_t>(size.height)}
    { }

    const PanoramaOID& oid() const { return oid_; }

    TId frameId() const { return frameId_; }

    geolib3::Heading heading() const { return geolib3::Heading{heading_}; }

    geolib3::Degrees tilt() const { return geolib3::Degrees{tilt_}; }

    geolib3::Degrees horizontalFOV() const { return geolib3::Degrees{horizontalFOV_}; }

    common::Size size() const { return {width_, height_}; }

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

    PanoramaToFrame() = default;

    template<typename T>
    static auto introspect(T& t)
    {
        return std::tie(t.oid_, t.frameId_, t.heading_, t.tilt_,
                        t.horizontalFOV_, t.width_, t.height_);
    }

    PanoramaOID oid_;
    TId frameId_;
    double heading_;
    double tilt_;
    double horizontalFOV_;
    std::uint16_t width_;
    std::uint16_t height_;

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

using PanoramaToFrames = std::vector<PanoramaToFrame>;

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