//=========================================================================
//  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_windtunnel_qt_qtOpenFoamRunner_h
#define smtk_simulation_windtunnel_qt_qtOpenFoamRunner_h

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

#include <QObject>
#include <QString>
#include <QStringList>
#include <QTextStream>

class QDialog;
class QDir;
class QFile;
class QPlainTextEdit;
class QProcess;
class QWidget;

#define DEFAULT_CONTAINER_ENGINE "docker" // for testing, substitute something like "nodocker"

#define OPENFOAM_DOCKER_REGISTRY "docker.io"
#define OPENFOAM_DOCKER_IMAGE_TAG "2312" // for testing, substitute something like "2000"
#define OPENFOAM_DOCKER_IMAGE "opencfd/openfoam-run:" OPENFOAM_DOCKER_IMAGE_TAG

namespace smtk
{
namespace simulation
{
namespace windtunnel
{

/**\brief Singleton class for launching OpenFOAM apps as external processes. */

class SMTKWINDTUNNELQTEXT_EXPORT qtOpenFoamRunner : public QObject
{
  Q_OBJECT
  using Superclass = QObject;

public:
  static qtOpenFoamRunner* instance(QObject* parent = nullptr);
  void setParentWidget(QWidget* widget);

  enum ProcessState
  {
    NotRunning = 0,
    Starting,
    Running
  };

  void useOpenFoamDocker(bool enabled) { m_useDocker = enabled; }

  /** \brief Launch OpenFOAM application.
     *
     * Runs the specified application as a detached process, setting up log
     * file, polling for completion, and notifying app when process has finished.
     */
  void start(const QString& application, const QString& caseFolder, const QStringList& arguments);

  ProcessState state() const { return m_state; }

  void showLogFile(const QString& path);

Q_SIGNALS:
  void finished(qint64 pid, int exitCode);
  void started(qint64);

public Q_SLOTS:

protected Q_SLOTS:
  void onProcessStarted();

protected:
  qtOpenFoamRunner(QObject* parent = nullptr);
  ~qtOpenFoamRunner() override;

  void startRefineMesh(const QString& caseFolder);
  void continueRefineMesh();

  QProcess* m_process = nullptr;
  QWidget* m_parentWidget = nullptr;
  QDir* m_processDir = nullptr;
  ProcessState m_state = ProcessState::NotRunning;
  qint64 m_pid = 0;

  // Classes for displaying the logfile
  QDialog* m_logDialog = nullptr;
  QFile* m_logFile = nullptr;
  QPlainTextEdit* m_textEdit = nullptr;

  bool m_useDocker = false;

  // Internal vars for sequencing refineMesh runs
  int m_refineMeshCurrentStep = 0; // current iteration number
  int m_refineMeshLastStep = 0;    // final iteration number
  QString m_refineMeshApp;         // toggles between "topoSet" and "refineMesh"
  QString m_refineMeshCaseFolder;
};

} // namespace windtunnel
} // namespace simulation
} // namespace smtk

#endif
