/* FILE: timedriver.h            -*-Mode: c++-*-
 *
 * Example concrete Oxs_Driver class.
 *
 */

#ifndef _OXS_TIMEDRIVER
#define _OXS_TIMEDRIVER

#include <vector>

#include "simstate.h"
#include "key.h"
#include "driver.h"
#include "timeevolver.h"

OC_USE_STD_NAMESPACE;

/* End includes */

class Oxs_TimeDriver:public Oxs_Driver {
private:
  Oxs_OwnedPointer<Oxs_TimeEvolver> evolver_obj; // Evolver basket
  Oxs_Key<Oxs_TimeEvolver> evolver_key;

  vector<OC_REAL8m> stopping_time;  // Seconds
  vector<OC_REAL8m> stopping_dm_dt; // deg/ns

  Oxs_Output* max_dm_dt_obj_ptr; // Pointer to object providing
  /// max dm/dt data.  This is needed to determine StageDone events.

  // State-based outputs, maintained by the driver.  These are
  // conceptually public, but are specified private to force
  // clients to use the output_map interface in Oxs_Director.
#define OSO_DECL(name) \
void Fill__##name##_output(const Oxs_SimState&); \
Oxs_ScalarOutput<Oxs_TimeDriver> name##_output
  OSO_DECL(last_timestep);
  OSO_DECL(simulation_time);
#undef OSO_DECL

  // Done checks, called by parent Oxs_Driver::IsStageDone and
  // Oxs_Driver::IsRunDone functions.
  virtual OC_BOOL ChildIsStageDone(const Oxs_SimState& state) const;
  virtual OC_BOOL ChildIsRunDone(const Oxs_SimState& state) const;

  // Disable copy constructor and assignment operator by declaring
  // them without defining them.
  Oxs_TimeDriver(const Oxs_TimeDriver&);
  Oxs_TimeDriver& operator=(const Oxs_TimeDriver&);

public:
  Oxs_TimeDriver(const char* name,    // Child instance id
                 Oxs_Director* newdtr, // App director
                 const char* argstr);  // MIF input block parameters
  virtual const char* ClassName() const; // ClassName() is
  /// automatically generated by the OXS_EXT_REGISTER macro.
  virtual OC_BOOL Init();
  virtual ~Oxs_TimeDriver();

  virtual void StageRequestCount(unsigned int& min,
				 unsigned int& max) const;
  // Number of stages wanted by driver

  // Generic interface
  virtual Oxs_ConstKey<Oxs_SimState> GetInitialState() const;

  // Use FillState* and FillNewStageState* routines inherited from
  // parent.

  virtual OC_BOOL InitNewStage(Oxs_ConstKey<Oxs_SimState> state,
                            Oxs_ConstKey<Oxs_SimState> prevstate);

  virtual  OC_BOOL
  Step(Oxs_ConstKey<Oxs_SimState> current_state,
       const Oxs_DriverStepInfo& step_info,
       Oxs_ConstKey<Oxs_SimState>& next_state);
  // Returns true if step was successful, false if
  // unable to step as requested.

  // Time driver interface
  virtual void FillStateSupplemental(Oxs_SimState& work_state) const;
  /// FillStateSupplemental is called from time evolvers to adjust timestep.
};

#endif // _OXS_TIMEDRIVER
