#include "../../src/ErrorSimulator.hpp"
#include "../Tests.hpp"
#include "core/utils/Clock.hpp"

static void testUpdate() {
    Core::Clock c;
    Core::Clock::Nanos n1 = 0;
    Core::Clock::Nanos n2 = 0;
    Core::Clock::Nanos n3 = 0;
    Core::Clock::Nanos n4 = 0;
    CORE_TEST_ERROR(c.update(n1));
    CORE_TEST_ERROR(c.update(n2));
    CORE_TEST_ERROR(c.update(n3));
    CORE_TEST_ERROR(c.update(n4));
    CORE_TEST_TRUE(n1 == 0);
    CORE_TEST_TRUE(n2 > 0);
    CORE_TEST_TRUE(n3 > 0);
    CORE_TEST_TRUE(n4 > 0);
}

static void testUpdatesPerSecond() {
    Core::Clock c;
    for(int i = 0; i < 1000; i++) {
        Core::Clock::Nanos n = 0;
        CORE_TEST_ERROR(c.update(n));
    }
    CORE_TEST_TRUE(c.getUpdatesPerSecond() > 0.0f);
}

static void testWait(Core::Clock::Nanos wait) {
    Core::Clock c;
    Core::Clock::Nanos n = 0;
    CORE_TEST_ERROR(c.update(n));
    CORE_TEST_ERROR(Core::Clock::wait(wait));
    Core::Clock::Nanos n2 = 0;
    CORE_TEST_ERROR(c.update(n2));
    CORE_TEST_TRUE(n2 >= wait && n2 <= wait * 13 / 10);
}

static void testFail() {
#ifdef ERROR_SIMULATOR
    Core::Clock::Nanos n = 0;
    Core::Fail::timeGet = true;
    CORE_TEST_EQUAL(Core::ErrorCode::TIME_NOT_AVAILABLE,
                    Core::Clock::getNanos(n));
    Core::Fail::timeGet = false;
#endif
}

void Core::testClock(bool light) {
    testUpdate();
    testUpdatesPerSecond();
    testWait(light ? 5'000'000 : 50'000'000);
    testWait(light ? 50'000'000 : 1'300'000'000);
    testFail();
}