#ifndef ONETHREAD_H
#define ONETHREAD_H


#include <QObject>
#include <QTimer>
#include <functional>
#include <QThread>

/**
 * 这个类提供了一种方便的线程调用方法,可以直接用信号将需要放入新线程
 * 运行的函数传递给这个类,然后就会在槽函数中运行这个函数
 * 使用方法:
 *      1. 创建一个OneThread对象,传入一个QThread对象,或者不传入,会自动创建一个QThread对象
 *      2. 使用addTask或者addTaskRunOne添加任务,addTask会进入循环,addTaskRunOne只会执行一次
 *      3. 不使用addTask,直接使用bindTask绑定函数和参数,手动触发信号,注意,触发信号前,要先开启子线程getThread()->start();
 * 
 *  使用示例:
 *     1、非成员函数 
 *          void func(int a, int b) { std::cout << a + b << std::endl; }
 *          thread.add_task(func, 1, 2);
 *     2、成员函数 
 *          void A::func(int a, int b) { std::cout << a + b << std::endl; }
 *          A a;
 *          thread.add_task(&A::func, &a, 1, 2);
 */


class OneThread : public QObject
{
    Q_OBJECT
public:
    explicit OneThread(QThread* thread, QObject* parent = nullptr);
    explicit OneThread(QObject* parent = nullptr);
    ~OneThread();
    /* 获取子线程 */
    QThread* getThread() const { return m_thread; }
    /* 停止子线程 */
    void stopThread() { m_threadRunning = false; }

    /* 添加任务,开启子线程,这个会进入循环,不会退出,调用stopThread会停止线程 */
    template<typename F, typename... Args>
    void addTask(F&& f, Args&&... args)
    {
        if(!m_thread->isRunning())
        {
            m_thread->start();
        }
        std::function<void(void)> task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        emit signal_runTask(task);
    }
    /* 添加任务,开启子线程,这里只会执行一次 */
    template<typename F, typename... Args>
    void addTaskRunOne(F&& f, Args&&... args)
    {
        if(!m_thread->isRunning())
        {
            m_thread->start();
        }
        std::function<void(void)> task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        emit signal_runTaskRunOne(task);
    }
    /* 将函数与参数绑定 */
    template<typename F, typename... Args>
    std::function<void(void)> bindTask(F&& f, Args&&... args)
    {
        return std::bind(std::forward<F>(f), std::forward<Args>(args)...);
    }

signals:
    void signal_runTask(std::function<void(void)> func);
    void signal_runTaskRunOne(std::function<void(void)> func);

private slots:
    void do_runTask(std::function<void(void)> func);
    void do_runTaskRunOne(std::function<void(void)> func);

private:
    bool m_threadRunning = false;
    QThread* m_thread = nullptr;
    QTimer m_timer;    /* 定时器 */

    std::function<void(void)> m_func;    /* 运行的函数 */
};



#endif // ONETHREAD_H