#include "task_impl.h"
#include "magic_strings.h"
#include "include/yandex/maps/mrc/toloka_client/known_solution.h"
#include <maps/libs/json/include/builder.h>
#include <maps/libs/json/include/value.h>

#include <boost/lexical_cast.hpp>

#include <utility>

namespace maps {
namespace mrc {
namespace toloka {
namespace io {

/**
 * https://tech.yandex.ru/toloka/api/doc/concepts/tasks-docpage/
 */
Task::Impl::Impl(const json::Value& value)
    : id_(value[FIELD_ID].as<std::string>())
    , poolId_(value[FIELD_POOL_ID].as<std::string>())
    , createdAt_(chrono::parseIsoDateTime(value[FIELD_CREATED].as<std::string>()))
    , inputValues_(value[FIELD_INPUT_VALUES])
{
    hasInfiniteOverlap_ = false;
    if (value.hasField(FIELD_INFINITE_OVERLAP)) {
        hasInfiniteOverlap_ = value[FIELD_INFINITE_OVERLAP].as<bool>();
    }
    if (!hasInfiniteOverlap_) {
        if (value.hasField(FIELD_OVERLAP)) {
            overlap_ = value[FIELD_OVERLAP].as<size_t>();
        }
    }
    if (value.hasField(FIELD_KNOWN_SOLUTIONS)) {
        for (const auto& ks : value[FIELD_KNOWN_SOLUTIONS]) {
            knownSolutions_.emplace_back(
                ks[FIELD_OUTPUT_VALUES],
                ks[FIELD_CORRECTNESS_WEIGHT].as<double>()
            );
        }
    }
    if (value.hasField(FIELD_MESSAGE_ON_UNKNOWN_SOLUTION)) {
        messageOnUnknownSolution_
                = value[FIELD_MESSAGE_ON_UNKNOWN_SOLUTION].as<std::string>();
    }

}

void TaskCreationParams::Impl::toJson(json::ObjectBuilder builder) const
{
    builder[FIELD_POOL_ID] = poolId_;
    builder[FIELD_INPUT_VALUES] = inputValues_;

    if (!knownSolutions_.empty()) {
        builder[FIELD_KNOWN_SOLUTIONS] << [&](json::ArrayBuilder ab) {
            for (const auto& ks : knownSolutions_) {
                ab << [&](json::ObjectBuilder sb) {
                    sb[FIELD_OUTPUT_VALUES] = ks.outputValues();
                    sb[FIELD_CORRECTNESS_WEIGHT] = ks.correctnessWeight();
                };
            }
        };
    }
    if (!messageOnUnknownSolution_.empty()) {
        builder[FIELD_MESSAGE_ON_UNKNOWN_SOLUTION]
                = messageOnUnknownSolution_;
    }
    if (overlap_) {
        builder[FIELD_OVERLAP] = *overlap_;
    }
    builder[FIELD_INFINITE_OVERLAP] = hasInfiniteOverlap_;
}

std::string TaskCreationParams::Impl::toJson() const
{
    json::Builder builder;

    builder << [this](json::ObjectBuilder taskBuilder) {
        toJson(taskBuilder);
    };

    return builder.str();
}

} // namespace io
} // namespace toloka
} // namespace mrc
} // namespace maps
