//                                               -*- C++ -*-
/**
 *  @brief YACSEvaluation implements the evaluation of the models defined by an xml file
 *
 *  Copyright 2015-2026 EDF-Phimeca
 *
 *  This library is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#ifndef PERSALYS_YACSEVALUATION_HXX
#define PERSALYS_YACSEVALUATION_HXX

#include "persalys/PersalysPrivate.hxx"
#include <openturns/EvaluationImplementation.hxx>

#include <ydefx/Launcher.hxx>

namespace PERSALYS
{

/**
 * @class YACSEvaluation
 *
 * The class that implement the evaluation of an analytical function.
 */

class PERSALYS_BASE_API YACSEvaluation : public OT::EvaluationImplementation
{
  CLASSNAME

public:
  /** Default constructor */
  explicit YACSEvaluation(const OT::String & script = "");

  /** Virtual constructor */
  YACSEvaluation * clone() const override;

  /** Comparison operator */
  OT::Bool operator ==(const YACSEvaluation & other) const;

  /** String converter */
  OT::String __repr__() const override;
  OT::String __str__(const OT::String & offset = "") const override;

  /** Operator () */
  OT::Point operator() (const OT::Point & inP) const override;
  OT::Sample operator() (const OT::Sample & inS) const override;

  /** Accessor for input values */
  OT::Point getInputValues() const;
  void setInputValues(const OT::Point & inP);
  /** Accessor to the input variables names */
  OT::Description getInputVariablesNames() const;
  /** Accessor for input point dimension */
  OT::UnsignedInteger getInputDimension() const override;

  /** Accessor to the output variables names */
  OT::Description getOutputVariablesNames() const;
  void setOutputVariablesNames(const OT::Description & outDescription);
  /** Accessor for output point dimension */
  OT::UnsignedInteger getOutputDimension() const override;

  /** Accessor to the formulas */
  OT::String getCode() const;
  void setCode(const OT::String & code);

  /** Accessor to launching resource properties */
  ydefx::JobParametersProxy& jobParameters();
  const ydefx::JobParametersProxy& jobParameters() const;

  /** Generate script for JobParametersProxy */
  OT::String getJobParamsPythonScript(const OT::String & name) const;

  /** Method save() stores the object through the StorageManager */
  void save(OT::Advocate & adv) const override;

  /** Method load() reloads the object from the StorageManager */
  void load(OT::Advocate & adv) override;

  /** Stop callback */
  typedef  OT::Bool (*StopCallback)(void * state);
  virtual void setStopCallback(StopCallback callBack, void * state = nullptr);

  /** Running flag accessor */
  void setIsRunning(const OT::Bool isRunning) const;
  OT::Bool getIsRunning() const;

  /** Id dump accessor */
  void setDump(const OT::String & dump) const;
  OT::String getDump() const;

  /** Additional files to copy */
  void setExtraInputFiles(const OT::Description & extraInputFiles);

  /** Subdir accessor */
  void setWorkSubDir(const OT::String & workSubDir);

private:
  OT::Point inputValues_;
  OT::Description inDescription_;
  OT::Description outDescription_;
  ydefx::JobParametersProxy jobParams_;
  OT::String code_ = "";
  py2cpp::PyPtr jobModel_;
  std::pair< StopCallback, void *> stopCallback_;
  mutable OT::Bool isRunning_ = false;
  mutable OT::String dump_;

  // subdirectory identifying the model to copy coupling files
  OT::String workSubDir_;

  // extra files to copy to the remote node
  OT::Description extraInputFiles_;
};
}
#endif
