#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/device_attrs.h>

#include <string>
#include <utility>

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

namespace {

const std::string SOURCE = "source";
const std::string MODEL = "model";
const std::string HFOV  = "hfov";

} // namespace


DeviceAttrs::DeviceAttrs(const json::Value& value)
    : value_(value)
{}

DeviceAttrs::DeviceAttrs(const MrcDeviceAttrs& attrs)
    : value_{
        {SOURCE, json::Value(std::string(toString(FrameSource::Mrc)))},
        {MODEL, attrs.model ? json::Value(*(attrs.model)) : json::null},
    }
{}

DeviceAttrs::DeviceAttrs(const PanoramaDeviceAttrs& attrs)
    : value_{
        {SOURCE, json::Value(std::string(toString(FrameSource::Panorama)))},
        {HFOV, json::Value(attrs.horizontalFOV.value())},
    }
{}

const json::Value& DeviceAttrs::json() const {
    return value_;
}

FrameSource DeviceAttrs::source() const {
    FrameSource source;
    fromString(value_[SOURCE].as<std::string>(), source);
    return source;
}

MrcDeviceAttrs DeviceAttrs::mrc() const {
    MrcDeviceAttrs attrs;
    if (!value_[MODEL].isNull()) {
        attrs.model = value_[MODEL].as<std::string>();
    } else {
        attrs.model = std::nullopt;
    }

    return attrs;
}

PanoramaDeviceAttrs DeviceAttrs::panorama() const {
    REQUIRE(!value_[HFOV].isNull(),
            "Panorama projection horizontal FOV is not defined");

    return { .horizontalFOV = geolib3::Degrees{value_[HFOV].as<double>()}};
}

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