#include "threadcontroller.h"
#include <QDebug>

#if defined(Q_OS_WIN32)
#include <windows.h>
#include <tlhelp32.h>
#endif

#include <QPointer>

/* 获取线程数 */
int ThreadUtility::GetThreadCount(int processID)
{
#if defined(Q_OS_WIN32)
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
  
    HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
      qDebug()<<"CreateToolhelp32Snapshot 调用失败";
      return -1;
    }
    BOOL bMore = ::Process32First(hProcessSnap, &pe32);
  
    //printf("%-30s %-20s %-20s %-15s\n","szExeFile","th32ProcessID","th32ParentProcessID","cntThreads");
    while(bMore)
    {
      //printf("%-30s ",pe32.szExeFile);
      //printf("%-20d ",pe32.th32ProcessID);
      //printf("%-20d",pe32.th32ParentProcessID);
      ////显示进程的线程数
      //printf("%-15d\n",pe32.cntThreads);
      //int pid = getpid();
      bMore = Process32Next(hProcessSnap, &pe32);
      if(static_cast<int>(pe32.th32ProcessID) == processID)
      {
          //qDebug()<<"进程名称 = "<<QString::fromWCharArray(pe32.szExeFile);
          //qDebug()<<"进程ID = "<<pe32.th32ProcessID;
          //qDebug()<<"线程数量 = "<<pe32.cntThreads;
          return static_cast<int>(pe32.cntThreads);
      }
    }
    return -1;
#elif defined(Q_OS_LINUX)
    return -1;
#endif
}
bool ThreadUtility::BlockExitThread(QThread *thread, unsigned long msecs)
{
    thread->quit();
    thread->requestInterruption();
    bool isSuccess = false;
    if(!thread->wait(msecs))
    {
        qDebug()<<"线程异常结束"<<thread;
        thread->terminate();
        if(!thread->wait(20000)) qDebug()<<"线程terminate异常";
    }
    else
    {
        qDebug()<<"线程正常结束"<<thread;
        isSuccess = true;
    }
    return isSuccess;
}
/* 工作线程 */
ThreadWorker::ThreadWorker()
    : QObject(nullptr)
    , m_pWorkTimer(nullptr)
    , m_bInited(false)
    , m_nInterval(1000)
{
    m_pWorkTimer = new QTimer(nullptr);
    connect(m_pWorkTimer, &QTimer::timeout, this, &ThreadWorker::OnWorkTimer, Qt::QueuedConnection);
    connect(this, &ThreadWorker::sig_StartWorkTimer, this, &ThreadWorker::OnStartWorkTimer, Qt::QueuedConnection);
    
    QThread *pHostThread = new QThread(nullptr);
    pHostThread->start();
    moveToThread(pHostThread);                      /* 将本实例移动到新线程中,其实就是将事件循环等移过去 */
    m_pWorkTimer->moveToThread(pHostThread);        /* 将定时器移到新线程中,定时器触发的槽函数就会运行在新线程中 */
    /*----------------------------------------------------------------
     * 对线程执行quit会发生: 结束线程的事件循环(线程里的对象不再能接受任何信号, 除了deleteLater), 发送finished信号
     * 宿主线程对象和工作对象都在同一个线程, 所以用DirectConnection
     * 这里是一个序列: 对线程执行quit -> 线程发送finished信号 -> 工作对象释放 -> 线程对象释放
    ----------------------------------------------------------------*/
    connect(pHostThread, &QThread::finished, this, &ThreadWorker::deleteLater, Qt::DirectConnection);
    connect(this, &ThreadWorker::destroyed, pHostThread, &QThread::deleteLater, Qt::DirectConnection);
    
    WorkerCollector::Instance()->AddWorker(this);
}

ThreadWorker::~ThreadWorker()
{
    
}
//在子线程执行(m_pWorkTimer已被移至线程)
void ThreadWorker::OnStartWorkTimer(int msecs)
{
    m_nInterval = (msecs==-1)?10:msecs;
    if(msecs == -1) m_pWorkTimer->setSingleShot(true);
    m_pWorkTimer->start(0);
}

//Start方法被主线程调用, 内容在主线程执行
void ThreadWorker::Start(int interval)
{
    QMutexLocker lockerInited(&m_mutexInited);
    m_bInited = false;
    emit sig_StartWorkTimer(interval);
}

void ThreadWorker::NonBlockStop()
{
    QThread *pThread = dynamic_cast<QThread*>(thread());
    if(pThread == nullptr) return;
    pThread->quit();
    pThread->requestInterruption();
}
//该方法只能被主线程调用
//否则报错: Thread tried to wait on itself
bool ThreadWorker::BlockStop(unsigned long msecs)
{
    return ThreadUtility::BlockExitThread(thread(), msecs);;
}

void ThreadWorker::SetInterval(int interval)
{
    m_pWorkTimer->setInterval(interval);
}

//OnWorkTimer在其他线程执行
void ThreadWorker::OnWorkTimer()
{
    m_pWorkTimer->setInterval(m_nInterval);
    /* 初始化锁 */
    m_mutexInited.lock();
    if(!m_bInited)
    {
        m_bInited = true;
        DoInit();
    }
    m_mutexInited.unlock();

    DoWork();
    emit sig_Ticked(this);
    //工作对象非循环且内容执行完毕
    if(m_pWorkTimer->isSingleShot())
    {
        NonBlockStop();
        return;
    }
    //主动调用NonBlockStop或BlockStop且未等待超时
    if(thread()->isInterruptionRequested())
    {
        m_pWorkTimer->stop();
        return;
    }
}

WorkerCollector::CollectorGarbo WorkerCollector::garbo;
WorkerCollector* WorkerCollector::sm_pInstance = new WorkerCollector();     //初始化静态单例(饿汉)

//在这里释放那些: 直到程序结束还没有被释放的工作对象
WorkerCollector::~WorkerCollector()
{
    sm_pInstance = nullptr;
    auto pred = [](QPointer<ThreadWorker> x){return x != nullptr;};
    QList<QPointer<ThreadWorker>> remainWorkers;
    std::copy_if(m_listWorkers.begin(), m_listWorkers.end(), std::back_inserter(remainWorkers), pred);
    qDebug()<<"线程管理器释放: 待释放工作对象个数"<<remainWorkers.count();
    int counter = 0;
    for(QPointer<ThreadWorker> pWorker: remainWorkers)
    {
        //注意: 这里如果是停止超时的情况, 说明工作对象正在执行内容, 直接调用delete可能会导致崩溃
        //而且这里不能使用deleteLater来释放工作对象, 因为线程的事件循环已经退出了
        if(!pWorker->BlockStop(5000)) continue;
        delete pWorker;
        counter++;
    }
    qDebug()<<"已释放工作对象: "<<counter;
    m_listWorkers.clear();
}

void WorkerCollector::AddWorker(ThreadWorker *worker)
{
    QPointer<ThreadWorker> pWorker(worker);
    m_listWorkers.append(pWorker);
}