#ifndef TEST_HELPERS_TEST_MAIN_THREAD_H
#define TEST_HELPERS_TEST_MAIN_THREAD_H

#include <memory>

#include "test/helpers/test_fixture.h"
#include "test/helpers/test_thread.h"
#include "torrent/common.h"
#include "torrent/system/thread.h"

class TestMainThread : public torrent::system::Thread {
public:
  static std::unique_ptr<TestMainThread> create();
  static std::unique_ptr<TestMainThread> create_with_mock();
  static void                            destroy();

  const char*         name() const override  { return "rtorrent test main"; }

  void                init_thread() override;
  void                cleanup_thread() override;

  void                test_set_cached_time(std::chrono::microseconds t);
  void                test_add_cached_time(std::chrono::microseconds t);
  void                test_process_events_without_cached_time();

private:
  TestMainThread() = default;

  void                      call_events() override;
  std::chrono::microseconds next_timeout() override;
};

class TestFixtureWithMainThread : public test_fixture {
public:
  void setUp() override;
  void tearDown() override;

  std::unique_ptr<TestMainThread> m_main_thread;
};

class TestFixtureWithMainAndDiskThread : public test_fixture {
public:
  void setUp() override;
  void tearDown() override;

  std::unique_ptr<TestMainThread> m_main_thread;
};

class TestFixtureWithMainAndTrackerThread : public test_fixture {
public:
  void setUp() override;
  void tearDown() override;

  std::unique_ptr<TestMainThread> m_main_thread;
};

class TestFixtureWithMainNetTrackerThread : public test_fixture {
public:
  void setUp() override;
  void tearDown() override;

  std::unique_ptr<TestMainThread> m_main_thread;
};

class TestFixtureWithMockAndMainThread : public test_fixture {
public:
  void setUp() override;
  void tearDown() override;

  std::unique_ptr<TestMainThread> m_main_thread;
};

#endif // TEST_HELPERS_TEST_MAIN_THREAD_H
