#include "tool.h"

#include <maps/libs/common/include/make_batches.h>
#include <maps/libs/json/include/builder.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/suncalc.h>
#include <yandex/maps/mrc/toloka_client/task_suite.h>

#include <boost/range/algorithm_ext/erase.hpp>

#include <algorithm>
#include <chrono>

namespace maps {
namespace mrc {
namespace toloka {

namespace {

constexpr size_t NUM_TASKS_IN_SUITE = 6;

const std::string FIELD_SOURCE = "source";

const std::string MRC_BROWSER_URL
        = "https://mrc-browser.maps.yandex.net/feature/";

using Tasks = std::vector<io::TaskSuiteItem>;
using TaskItr = Tasks::iterator;

json::Value makeInputValues(const std::string& source)
{
    json::Builder builder;
    builder << [&](json::ObjectBuilder b) {
        b[FIELD_SOURCE] = source;
    };
    return json::Value::fromString(builder.str());
}

} // namespace

db::TIds::iterator DetectionTasksGenerator::generate(
        db::TIds::iterator beg,
        db::TIds::iterator end,
        size_t taskSuitesCount,
        size_t overlap)
{
    const size_t tasksCnt = NUM_TASKS_IN_SUITE * taskSuitesCount;
    size_t leftTasksCnt = tasksCnt;
    db::Gateway gtw(txn_);
    auto portionEnd = beg;

    Tasks tasks;

    while (leftTasksCnt > 0 && beg < end) {
        portionEnd = std::min(end, beg + leftTasksCnt);
        auto portion = gtw.loadFeaturesByIds(db::TIds{beg, portionEnd});
        boost::range::remove_erase_if(portion,
            [](const db::Feature& f) {
                return common::DayPart::Night ==
                    common::getDayPart(f.timestamp(), f.geodeticPos().y(), f.geodeticPos().x());
            }
        );

        for (const auto& feature : portion) {
            const std::string source
                = MRC_BROWSER_URL + std::to_string(feature.id()) + "/image";
            tasks.emplace_back(makeInputValues(source));
        }

        beg = portionEnd;
        leftTasksCnt = tasksCnt - tasks.size();
    }

    INFO() << "Number of features loaded: " << tasks.size();
    std::random_shuffle(tasks.begin(), tasks.end());

    for (auto batch : maps::common::makeBatches(tasks, NUM_TASKS_IN_SUITE)) {
        Tasks t(batch.begin(), batch.end());
        io::TaskSuiteCreationParams tsParams(poolId_, std::move(t));
        tsParams.setOverlap(overlap);
        tolokaClient_.postTaskSuite(tsParams);
    }
    return portionEnd;
}

} // toloka
} // mrc
} // maps
