#pragma once

#include <functional>

#include "Evt.h"
#include "DllDefines.h"

class UTILITYDLL CThread
{
    friend UINT __cdecl MyThreadFunction(LPVOID lpParam);

private:
    HANDLE m_threadHandle;
    CWinThread* m_pWinThread;
    DWORD m_threadId;
    const TCHAR* m_threadName;
    CEvt m_eventStarted;
    void _Run();
    bool bIsInterrupted;

public:
    CThread(const TCHAR* threadName, int nPrority = THREAD_PRIORITY_NORMAL);
    static CThread* Create(const TCHAR* threadName, std::function<void()> f, int nPrority = THREAD_PRIORITY_NORMAL);
    virtual ~CThread(void);
    bool SetThreadPriority(int nPriority);
    virtual void Run() = 0;
    bool Start();
    bool Wait(DWORD dwMilliSeconds = INFINITE);
    bool WaitStarted(DWORD dwMilliSeconds = INFINITE);
    DWORD GetThreadId();
    HANDLE GetThreadHandle();
    const TCHAR* GetName()
    {
        return m_threadName;
    }

    void Interrupt();
    bool IsInterrupted();
    void SetThreadName(const TCHAR* threadName);
    static void SetThreadName(DWORD dwThreadID, const char* threadName);
};
