#include "geo_block.h"
#include "lables.h"

#include <util/string/cast.h>

namespace NSaas {
    TGeoBlock::TPointSet::TPointSet(NRTYServer::TMessage::TGeoObject& object, EGeoObjectKind kind)
        : InternalProtobuf(object)
    {
        Y_ASSERT(kind == EGeoObjectKind::SpecialPointSet || kind == EGeoObjectKind::PointSet);
        object.SetType(ToString(kind));
    }

    TGeoBlock::TPointSet& TGeoBlock::TPointSet::AddPoint(float lon, float lat) {
        InternalProtobuf.AddData(lon);
        InternalProtobuf.AddData(lat);
        return *this;
    }

    TGeoBlock::TRectSet::TRectSet(NRTYServer::TMessage::TGeoObject& object)
        : InternalProtobuf(object)
    {
        object.SetType(ToString(EGeoObjectKind::RectSet));
    }

    TGeoBlock::TRectSet& TGeoBlock::TRectSet::AddRect(float lowerLon, float lowerLat, float upperLon, float upperLat) {
        if (Y_UNLIKELY(lowerLon > upperLon))
            std::swap(lowerLon, upperLon);
        if (Y_UNLIKELY(lowerLat > upperLat))
            std::swap(lowerLat, upperLat);
        InternalProtobuf.AddData(lowerLon);
        InternalProtobuf.AddData(lowerLat);
        InternalProtobuf.AddData(upperLon);
        InternalProtobuf.AddData(upperLat);
        return *this;
    };

    TGeoBlock::TGeoBlock(NRTYServer::TMessage::TGeoData& geoProto)
        : InternalProtobuf(geoProto)
    {
    }

    TGeoBlock::TPointSet TGeoBlock::AddPointSet(const TString& layerName, bool geodetic) {
        auto* layer = InternalProtobuf.AddLayers();
        layer->SetLayer(layerName);
        auto* geoObject = layer->AddGeoDoc();
        const EGeoObjectKind kind = geodetic ? EGeoObjectKind::PointSet : EGeoObjectKind::SpecialPointSet;
        return TPointSet(*geoObject, kind);
    }

    TGeoBlock::TRectSet TGeoBlock::AddRectSet(const TString& layerName) {
        auto* layer = InternalProtobuf.AddLayers();
        layer->SetLayer(layerName);
        auto* geoObject = layer->AddGeoDoc();
        return TRectSet(*geoObject);
    }

    NJson::TJsonValue TGeoBlock::ToJson(const NRTYServer::TMessage::TGeoLayer& layer) {
        auto nItems = layer.GeoDocSize();
        NJson::TJsonValue json(NJson::JSON_MAP);
        NJson::TJsonValue coords(NJson::JSON_ARRAY);
        if (nItems == 1) {
            const auto& doc = layer.GetGeoDoc(0);
            json.InsertValue(NJsonFormat::GeoLayerKindLable, doc.GetType());
            for (float v : doc.get_arr_data()) {
                coords.AppendValue(v);
            }
        } else {
            // more than one GeoObject is not supported
            json.InsertValue(NJsonFormat::GeoLayerKindLable, ToString(EGeoObjectKind::SpecialPointSet));
        }
        json.InsertValue(NJsonFormat::CoordsLable, coords);

        NJson::TJsonValue result(NJson::JSON_MAP);
        result.InsertValue(NJsonFormat::TypeLable, "#e");
        result.InsertValue(NJsonFormat::ValueLable, json);
        return result;
    }
}
