#ifndef COMMANDDISPATCHER_H
#define COMMANDDISPATCHER_H

#include <QFuture>
#include <QVariant>
#include <deque>

#include "Task.h"

namespace nemo_interface {

class TaskDispatcher : QObject {
public:
  TaskDispatcher();
  ~TaskDispatcher();
  //!
  //! \brief dispatch Dispatches a task.
  //! \param c The task to dispatch.
  //! \return Returns a future containing the QVariant which the task c
  //! returned.
  //!
  std::future<QVariant> dispatch(std::unique_ptr<Task> c);
  //!
  //! \brief dispatchNext Dispatches the task c as the next task.
  //! \param c The task to dispatch.
  //! \return Returns a future containing the QVariant which the task c
  //! returned.
  //!
  std::future<QVariant> dispatchNext(std::unique_ptr<Task> c);
  //!
  //! \brief clear Clears the task list.
  //!
  void clear();
  //!
  //! \brief start Starts task dispatching. This function can be called after
  //! dispatching has been stopped, e.g. by stop() or reset().
  //!
  void start();
  //!
  //! \brief stop Stops task dispatching.
  //!
  //! Stops taks dispatching. The dispatcher will wait for the current task to
  //! complete and than terminate the dispatcher thread. After stop() has been
  //! called isInterruptionRequested will return true. This can be used to
  //! permaturely terminate a task.
  //!
  void stop();
  //!
  //! \brief reset Clears the task list and stops dispatching.
  //!
  void reset();
  bool isInterruptionRequested();
  bool isRunning();

  std::size_t pendingTasks();

protected:
  void run();

private:
  QFuture<void> _future;

  std::deque<std::unique_ptr<Task>> _taskQueue;
  std::deque<std::promise<QVariant>> _promiseQueue;
  bool _running;
  std::mutex _mutex;
};
} // namespace nemo_interface

#endif // COMMANDDISPATCHER_H
