#include <maps/wikimap/mapspro/services/mrc/libs/toloka_manager/include/house_number_recognition.h>
#include <maps/libs/json/include/builder.h>
#include <maps/libs/json/include/std.h>
#include <maps/libs/json/include/value.h>

namespace maps::mrc::toloka {

constexpr maps::enum_io::Representations<HouseNumberRecognitionState>
HOUSE_NUMBER_RECOGNITION_STATE_TO_STRING{
    {HouseNumberRecognitionState::Ok, "ok"},
    {HouseNumberRecognitionState::NotRecognized, "not-recognized"},
    {HouseNumberRecognitionState::NotHouseNumber, "not-house-number"},
    {HouseNumberRecognitionState::NotLoaded, "not-loaded"},
};

DEFINE_ENUM_IO(HouseNumberRecognitionState, HOUSE_NUMBER_RECOGNITION_STATE_TO_STRING);

void HouseNumberRecognitionInput::json(json::ObjectBuilder builder) const
{
    builder[FIELD_IMAGE] = imageUrl();
    builder[FIELD_BBOX] = bbox_;
}

template <>
HouseNumberRecognitionInput parseJson(const json::Value& jsonInput)
{
    auto imageUrl = jsonInput[FIELD_IMAGE].as<std::string>();
    auto bbox = common::ImageBox::fromJson(jsonInput[FIELD_BBOX]);
    return HouseNumberRecognitionInput(std::move(imageUrl), std::move(bbox));
}

void HouseNumberRecognitionOutput::json(json::ObjectBuilder builder) const
{
    builder[FIELD_STATE] = toString(state_);
    if (!houseNumber_.empty()) {
        builder[FIELD_HOUSE_NUMBER] = houseNumber_;
    }
}

template <>
HouseNumberRecognitionOutput parseJson(const json::Value& jsonOutput)
{
    HouseNumberRecognitionState state;
    fromString(jsonOutput[FIELD_STATE].as<std::string>(), state);

    std::string houseNumber;
    if (jsonOutput.hasField(FIELD_HOUSE_NUMBER)) {
        houseNumber = jsonOutput[FIELD_HOUSE_NUMBER].as<std::string>();
    }

    return HouseNumberRecognitionOutput(state, std::move(houseNumber));
}

/**
 * HouseNumberRecognitionInput implementation
 */

HouseNumberRecognitionInput::HouseNumberRecognitionInput(
    std::string imageUrl, common::ImageBox bbox)
    : imageUrl_(std::move(imageUrl)), bbox_(std::move(bbox))
{
}

const std::string& HouseNumberRecognitionInput::imageUrl() const { return imageUrl_; }

const common::ImageBox& HouseNumberRecognitionInput::bbox() const { return bbox_; }

/**
 * HouseNumberRecognitionOutput implementation
 */

HouseNumberRecognitionOutput::HouseNumberRecognitionOutput(
    HouseNumberRecognitionState state, std::string houseNumber)
    : state_(state), houseNumber_(std::move(houseNumber))
{
}

HouseNumberRecognitionState HouseNumberRecognitionOutput::state() const { return state_; }

const std::string& HouseNumberRecognitionOutput::houseNumber() const {
    return houseNumber_;
}

bool operator==(const HouseNumberRecognitionOutput& lhs, const HouseNumberRecognitionOutput& rhs)
{
    return lhs.introspect() == rhs.introspect();
}

bool operator<(const HouseNumberRecognitionOutput& lhs, const HouseNumberRecognitionOutput& rhs)
{
    return lhs.introspect() < rhs.introspect();
}

std::ostream& operator<<(std::ostream& out, const HouseNumberRecognitionOutput& taskOutput)
{
    json::Builder builder(out);
    builder << [&](json::ObjectBuilder b) {
        taskOutput.json(b);
    };
    return out;
}


} // namespace maps::mrc::toloka
