//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================

#ifndef smtk_simulation_ace3p_qt_qtOperationLauncher_h
#define smtk_simulation_ace3p_qt_qtOperationLauncher_h

#include "smtk/simulation/ace3p/qt/Exports.h"

#include "smtk/common/ThreadPool.h"
#include "smtk/operation/Operation.h"

#include <QObject>
#include <QString>

#include <future>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

class qtOperationLauncher;

/// This class will be responsible for notifying the original caller of an
/// operation that the result from said operation is ready.
class SMTKACE3PQTEXT_EXPORT ResultHandler : public QObject
{
  Q_OBJECT

public:
  explicit ResultHandler();
  smtk::operation::Operation::Result waitForResult();
  std::shared_future<smtk::operation::Operation::Result>& future() { return m_future; }

signals:
  /// Externally accessible signal on the primary thread containing the
  /// operation results.
  void resultReady(smtk::operation::Operation::Result result);

private:
  friend class qtOperationLauncher;
  std::shared_future<smtk::operation::Operation::Result> m_future;
};

/// An operation launcher that emits a signal containing the operation's result
/// after the operation has successfully executed.
///
/// qtOperationLauncher is a functor that executes an operation in a separate
/// thread and emits a signal with the operation's result on the thread
/// containing the launcher.
class SMTKACE3PQTEXT_EXPORT qtOperationLauncher : public QObject
{
  Q_OBJECT

public:
  static constexpr const char* const type_name = "smtk::simulation::ace3p::qtOperationLauncher";

  /* The primary execution method of this functor. This function returns a new ResultHandler
   * for each operation.
   */
  std::shared_ptr<ResultHandler> operator()(const smtk::operation::Operation::Ptr& operation);

signals:
  /// Internal signal from the executing subthread to the primary thread
  /// indicating the completion of the operation.
  void operationHasResult(QString parametersName, QString resultName, QPrivateSignal);

private:
  /// Internal method run on a subthread to invoke the operation.
  smtk::operation::Operation::Result run(smtk::operation::Operation::Ptr operation);

  smtk::common::ThreadPool<smtk::operation::Operation::Result> m_threadPool;
};

} // namespace ace3p
} // namespace simulation
} // namespace smtk

#endif
