/* Distributed under the Apache License, Version 2.0.
   See accompanying NOTICE file for details.*/

#pragma once
#include "Controller/System.h"
#include "system/equipment/anesthesiamachine/SEAnesthesiaMachine.h"
class SEAnesthesiaMachineActionCollection;
class SEGasCompartment;
class SEGasSubstanceQuantity;
class SEFluidCircuitNode;
class SEFluidCircuitPath;
PULSE_BIND_DECL(AnesthesiaMachineData)

/**
 * @brief 
 * Generic anesthesia machine for positive pressure ventilation.
 */    
class PULSE_DECL AnesthesiaMachine : public SEAnesthesiaMachine, public PulseAnesthesiaMachine, public PulseSystem
{
  friend class PulseController;
  friend class PulseEngineTest;
protected:
  AnesthesiaMachine(PulseController& pc);
  PulseController& m_data;

public:
  virtual ~AnesthesiaMachine();

  void Clear();

  static void Load(const pulse::AnesthesiaMachineData& src, AnesthesiaMachine& dst);
  static pulse::AnesthesiaMachineData* Unload(const AnesthesiaMachine& src);
protected:
  static void Serialize(const pulse::AnesthesiaMachineData& src, AnesthesiaMachine& dst);
  static void Serialize(const AnesthesiaMachine& src, pulse::AnesthesiaMachineData& dst);

  // Set members to a stable homeostatic state
  void Initialize();
  // Set pointers and other member varialbes common to both homeostatic initialization and loading a state
  void SetUp();

  void StateChange();

  void PreProcess();
  void Process();
  void PostProcess();

  void CalculateScrubber();

  // Extending some functionality to these base class methods
  // We will update the Pulse Airway mode when these are called
  virtual void SetConnection(cdm::eAnesthesiaMachine_Connection c);
  virtual void InvalidateConnection();

  void CalculateSourceStatus();
  void CalculateEquipmentLeak();
  void SetConnection();
  void CalculateValveResistances();
  void CalculateVentilator();
  void CalculateGasSource();
  void CalculateCyclePhase();
  void CheckReliefValve();

  // Serializable member variables (Set in Initialize and in schema)
  bool         m_inhaling; 
  double       m_inspirationTime_s;
  double       m_O2InletVolumeFraction;
  double       m_currentbreathingCycleTime_s;
  double       m_totalBreathingCycleTime_s;

  // Stateless member variable (Set in SetUp())
  double m_dt_s;
  double m_dValveOpenResistance_cmH2O_s_Per_L;
  double m_dValveClosedResistance_cmH2O_s_Per_L;
  double m_dSwitchOpenResistance_cmH2O_s_Per_L;
  double m_dSwitchClosedResistance_cmH2O_s_Per_L;
  SEAnesthesiaMachineActionCollection* m_actions;
  SEGasCompartment*                    m_ambient;
  SEGasSubstanceQuantity*              m_ambientCO2;
  SEGasSubstanceQuantity*              m_ambientN2;
  SEGasSubstanceQuantity*              m_ambientO2;
  SEGasCompartment*                    m_gasSource;
  SEGasSubstanceQuantity*              m_gasSourceCO2;
  SEGasSubstanceQuantity*              m_gasSourceN2;
  SEGasSubstanceQuantity*              m_gasSourceO2;
  SEGasCompartment*                    m_scrubber;
  SEGasSubstanceQuantity*              m_scubberCO2;
  SEGasSubstanceQuantity*              m_scrubberN2;
  SEFluidCircuitNode*                  m_nVentilator;
  SEFluidCircuitPath*                  m_pAnesthesiaConnectionToEnvironment;
  SEFluidCircuitPath*                  m_pYPieceToExpiratoryLimb;
  SEFluidCircuitPath*                  m_pGasSourceToGasInlet;
  SEFluidCircuitPath*                  m_pInspiratoryLimbToYPiece;
  SEFluidCircuitPath*                  m_pSelectorToReliefValve;
  SEFluidCircuitPath*                  m_pEnvironmentToReliefValve;
  SEFluidCircuitPath*                  m_pSelectorToEnvironment;
  SEFluidCircuitPath*                  m_pEnvironmentToVentilator;
  SEFluidCircuitPath*                  m_pExpiratoryLimbToSelector;
  SEFluidCircuitPath*                  m_pSelectorToScrubber;
};
