#pragma once

#include <thread>
#include <functional>
#include <vector>
#include <mutex>
#include <queue>
#include <condition_variable>
#include "util/Util.h"

#include "util/Pointers.h"


class AgThreadPool
{
public:
    typedef std::thread Thread;
    typedef std::function<void ()> Task;

    AgThreadPool(const char* name, int maximumPoolSize, int workQueueCapacity);
    ~AgThreadPool();

    void execute(Task task);
    long getTasksCount();
    void setDebugInfoTimeout(long timeoutSec);
    void terminate();
    bool isTerminated();

protected:
    void managePool();
    void worker();

private:
    int maximumPoolSize;
    int workQueueCapacity;

    std::vector<Thread> threadPoolTasks;
    Thread poolManager;
    std::mutex taskQueueMutex;
    std::condition_variable notEmptyTaskQueue;
    std::condition_variable notFullTaskQueue;
    std::queue<Task> taskQueue;
    const char *name;
    long debugInfoTimeout;
    milliseconds lastDebugInfoTime;
    volatile bool _terminate;

    bool oneWarnFullWorkQueue;
};
