#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/gtest/gtest.h>
#include <maps/libs/json/include/builder.h>
#include <maps/libs/json/include/value.h>
#include <maps/tools/grinder/common/include/client.h>
#include <yandex/maps/mrc/unittest/grinder_fixture.h>

#include <chrono>
#include <thread>
#include <time.h>

namespace maps {
namespace mrc {
namespace unittest {
namespace tests {

namespace {

template <typename Duration, typename Predicate>
bool awaitConditionFor(Duration d, Predicate p)
{
    const std::chrono::milliseconds SLEEP_DELAY(100);
    std::chrono::milliseconds sleptFor(0);
    bool ok = false;
    while (!(ok = p()) && sleptFor < d) {
        std::this_thread::sleep_for(SLEEP_DELAY);
        sleptFor += SLEEP_DELAY;
    }
    return ok;
}

} // namespace

TEST(grinder_fixture_should, test_grinder_client_works)
{
    GrinderFixture fixture;
    const grinder::Config grinderConfig(fixture.grinderConfigPath());
    grinder::MongoTaskLogger grinderLogger(grinderConfig, std::chrono::seconds(10));
    grinder::Client client(grinderConfig, grinderLogger);
    EXPECT_EQ(client.listTaskIds().size(), 0u);
    const auto testTask = json::Value({{"type", json::Value("test_task")}});
    const auto taskId = client.submit(testTask);
    EXPECT_EQ(client.listTaskIds().at(0), taskId);
    EXPECT_TRUE(awaitConditionFor(
            std::chrono::seconds(5),
            [&]() { return client.listRecords(taskId).size() == 1u; }));
}

} //namespace tests
} //namespace unittest
} //namespace mrc
} //namespace maps
