#ifndef AWRCANFLASHER_TESTUTIL_H
#define AWRCANFLASHER_TESTUTIL_H

#include "pithread.h"
#include <atomic>

/**
 * Minimum wait thread start, switch context or another interthread communication action time. Increase it if tests
 * write "Start thread timeout reach!" message. You can reduce it if you want increase test performance.
 */
const int WAIT_THREAD_TIME_MS = 400;

const int THREAD_COUNT = 5;

class TestUtil: public PIObject {
PIOBJECT(TestUtil)
public:
    double threadStartTime;
    PIThread* thread = new PIThread();
    std::atomic_bool isRunning;
    std::function<void()> adapterFunctionDefault;

	TestUtil() : isRunning(false) {}

	bool createThread(const std::function<void()>&  fun = nullptr, PIThread* thread_ = nullptr) {
    	std::function<void()> actualFun = fun == nullptr ? adapterFunctionDefault : fun;
        if (thread_ == nullptr) thread_ = thread;
        thread_->startOnce([=](void*){
			isRunning = true;
        	actualFun();
        });
        return waitThread(thread_);
    }

    bool waitThread(PIThread* thread_, bool runningStatus = true) {
        PITimeMeasurer measurer;
        bool isTimeout = !thread_->waitForStart(WAIT_THREAD_TIME_MS);
        while (!isRunning) {
            isTimeout = WAIT_THREAD_TIME_MS <= measurer.elapsed_m();
            if (isTimeout) break;
            piUSleep(100);
        }

        threadStartTime = measurer.elapsed_m();

        if (isTimeout) piCout << "Start thread timeout reach!";

        if (threadStartTime > 1) {
            piCout << "Start time" << threadStartTime << "ms";
        } else if (threadStartTime > 0.001) {
            piCout << "Start time" << threadStartTime * 1000 << "mcs";
        } else {
            piCout << "Start time" << threadStartTime * 1000 * 1000 << "ns";
        }

        return !isTimeout;
    }
};

#endif //AWRCANFLASHER_TESTUTIL_H
