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

#include "stdafx.h"
#include "system/physiology/SERespiratorySystem.h"
#include "properties/SEScalarArea.h"
#include "properties/SEScalarFlowCompliance.h"
#include "properties/SEScalarFlowResistance.h"
#include "properties/SEScalar0To1.h"
#include "properties/SEScalarFrequency.h"
#include "properties/SEScalarPressure.h"
#include "properties/SEScalarVolume.h"
#include "properties/SEScalarVolumePerTime.h"

SERespiratorySystem::SERespiratorySystem(Logger* logger) : SESystem(logger)
{
  m_AlveolarArterialGradient = nullptr;
  m_CarricoIndex = nullptr;
  m_EndTidalCarbonDioxideFraction = nullptr;
  m_EndTidalCarbonDioxidePressure = nullptr; 
  m_ExpiratoryFlow = nullptr;
  m_InspiratoryExpiratoryRatio = nullptr;
  m_InspiratoryFlow = nullptr;
  m_PulmonaryCompliance = nullptr;
  m_PulmonaryResistance = nullptr;
  m_RespirationDriverPressure = nullptr;
  m_RespirationMusclePressure = nullptr;
  m_RespirationRate = nullptr;
  m_SpecificVentilation = nullptr;
  m_TidalVolume = nullptr;
  m_TotalAlveolarVentilation = nullptr;
  m_TotalDeadSpaceVentilation = nullptr;
  m_TotalLungVolume = nullptr;
  m_TotalPulmonaryVentilation = nullptr;
  m_TranspulmonaryPressure = nullptr;
}

SERespiratorySystem::~SERespiratorySystem()
{
  Clear();
}

void SERespiratorySystem::Clear()
{
  SESystem::Clear();

  SAFE_DELETE(m_AlveolarArterialGradient);
  SAFE_DELETE(m_CarricoIndex);
  SAFE_DELETE(m_EndTidalCarbonDioxideFraction);
  SAFE_DELETE(m_EndTidalCarbonDioxidePressure);
  SAFE_DELETE(m_ExpiratoryFlow);
  SAFE_DELETE(m_InspiratoryExpiratoryRatio);
  SAFE_DELETE(m_InspiratoryFlow);
  SAFE_DELETE(m_PulmonaryCompliance);
  SAFE_DELETE(m_PulmonaryResistance);
  SAFE_DELETE(m_RespirationDriverPressure);
  SAFE_DELETE(m_RespirationMusclePressure);
  SAFE_DELETE(m_RespirationRate);
  SAFE_DELETE(m_TidalVolume);
  SAFE_DELETE(m_TotalAlveolarVentilation);
  SAFE_DELETE(m_TotalDeadSpaceVentilation);
  SAFE_DELETE(m_TotalLungVolume);
  SAFE_DELETE(m_TotalPulmonaryVentilation);
  SAFE_DELETE(m_TranspulmonaryPressure);
}

const SEScalar* SERespiratorySystem::GetScalar(const std::string& name)
{
  if (name.compare("AlveolarArterialGradient") == 0)
    return &GetAlveolarArterialGradient();
  if (name.compare("CarricoIndex") == 0)
    return &GetCarricoIndex();
  if (name.compare("EndTidalCarbonDioxideFraction") == 0)
    return &GetEndTidalCarbonDioxideFraction();
  if (name.compare("EndTidalCarbonDioxidePressure") == 0)
    return &GetEndTidalCarbonDioxidePressure();
  if (name.compare("ExpiratoryFlow") == 0)
    return &GetExpiratoryFlow();
  if (name.compare("InspiratoryExpiratoryRatio") == 0)
    return &GetInspiratoryExpiratoryRatio();
  if (name.compare("InspiratoryFlow") == 0)
    return &GetInspiratoryFlow();
  if (name.compare("PulmonaryCompliance") == 0)
    return &GetPulmonaryCompliance();
  if (name.compare("PulmonaryResistance") == 0)
    return &GetPulmonaryResistance();
  if (name.compare("RespirationDriverPressure") == 0)
    return &GetRespirationDriverPressure();
  if (name.compare("RespirationMusclePressure") == 0)
    return &GetRespirationMusclePressure();
  if (name.compare("RespirationRate") == 0)
    return &GetRespirationRate();
  if (name.compare("SpecificVentilation") == 0)
    return &GetSpecificVentilation();
  if (name.compare("TidalVolume") == 0)
    return &GetTidalVolume();  
  if (name.compare("TotalAlveolarVentilation") == 0)
    return &GetTotalAlveolarVentilation();
  if (name.compare("TotalDeadSpaceVentilation") == 0)
    return &GetTotalDeadSpaceVentilation();
  if (name.compare("TotalLungVolume") == 0)
    return &GetTotalLungVolume();
  if (name.compare("TotalPulmonaryVentilation") == 0)
    return &GetTotalPulmonaryVentilation();
  if (name.compare("TranspulmonaryPressure") == 0)
    return &GetTranspulmonaryPressure();
  return nullptr;
}

bool SERespiratorySystem::HasAlveolarArterialGradient() const
{
  return m_AlveolarArterialGradient == nullptr ? false : m_AlveolarArterialGradient->IsValid();
}
SEScalarPressure& SERespiratorySystem::GetAlveolarArterialGradient()
{
  if (m_AlveolarArterialGradient == nullptr)
    m_AlveolarArterialGradient = new SEScalarPressure();
  return *m_AlveolarArterialGradient;
}
double SERespiratorySystem::GetAlveolarArterialGradient(const PressureUnit& unit) const
{
  if (m_AlveolarArterialGradient == nullptr)
    return SEScalar::dNaN();
  return m_AlveolarArterialGradient->GetValue(unit);
}

bool SERespiratorySystem::HasCarricoIndex() const
{
  return m_CarricoIndex == nullptr ? false : m_CarricoIndex->IsValid();
}
SEScalarPressure& SERespiratorySystem::GetCarricoIndex()
{
  if (m_CarricoIndex == nullptr)
    m_CarricoIndex = new SEScalarPressure();
  return *m_CarricoIndex;
}
double SERespiratorySystem::GetCarricoIndex(const PressureUnit& unit) const
{
  if (m_CarricoIndex == nullptr)
    return SEScalar::dNaN();
  return m_CarricoIndex->GetValue(unit);
}

bool SERespiratorySystem::HasEndTidalCarbonDioxideFraction() const
{
  return m_EndTidalCarbonDioxideFraction == nullptr ? false : m_EndTidalCarbonDioxideFraction->IsValid();
}
SEScalar0To1& SERespiratorySystem::GetEndTidalCarbonDioxideFraction()
{
  if (m_EndTidalCarbonDioxideFraction == nullptr)
    m_EndTidalCarbonDioxideFraction = new SEScalar0To1();
  return *m_EndTidalCarbonDioxideFraction;
}
double SERespiratorySystem::GetEndTidalCarbonDioxideFraction() const
{
  if (m_EndTidalCarbonDioxideFraction == nullptr)
    return SEScalar::dNaN();
  return m_EndTidalCarbonDioxideFraction->GetValue();
}

bool SERespiratorySystem::HasEndTidalCarbonDioxidePressure() const
{
  return m_EndTidalCarbonDioxidePressure==nullptr?false:m_EndTidalCarbonDioxidePressure->IsValid();
}
SEScalarPressure& SERespiratorySystem::GetEndTidalCarbonDioxidePressure()
{
  if(m_EndTidalCarbonDioxidePressure==nullptr)
    m_EndTidalCarbonDioxidePressure=new SEScalarPressure();
  return *m_EndTidalCarbonDioxidePressure;
}
double SERespiratorySystem::GetEndTidalCarbonDioxidePressure(const PressureUnit& unit) const
{
  if (m_EndTidalCarbonDioxidePressure == nullptr)
    return SEScalar::dNaN();
  return m_EndTidalCarbonDioxidePressure->GetValue(unit);
}

bool SERespiratorySystem::HasExpiratoryFlow() const
{
  return m_ExpiratoryFlow == nullptr ? false : m_ExpiratoryFlow->IsValid();
}
SEScalarVolumePerTime& SERespiratorySystem::GetExpiratoryFlow()
{
  if (m_ExpiratoryFlow == nullptr)
    m_ExpiratoryFlow = new SEScalarVolumePerTime();
  return *m_ExpiratoryFlow;
}
double SERespiratorySystem::GetExpiratoryFlow(const VolumePerTimeUnit& unit) const
{
  if (m_ExpiratoryFlow == nullptr)
    return SEScalar::dNaN();
  return m_ExpiratoryFlow->GetValue(unit);
}

bool SERespiratorySystem::HasInspiratoryExpiratoryRatio() const
{
  return m_InspiratoryExpiratoryRatio == nullptr ? false : m_InspiratoryExpiratoryRatio->IsValid();
}
SEScalar& SERespiratorySystem::GetInspiratoryExpiratoryRatio()
{
  if (m_InspiratoryExpiratoryRatio == nullptr)
    m_InspiratoryExpiratoryRatio = new SEScalar();
  return *m_InspiratoryExpiratoryRatio;
}
double SERespiratorySystem::GetInspiratoryExpiratoryRatio() const
{
  if (m_InspiratoryExpiratoryRatio == nullptr)
    return SEScalar::dNaN();
  return m_InspiratoryExpiratoryRatio->GetValue();
}

bool SERespiratorySystem::HasInspiratoryFlow() const
{
  return m_InspiratoryFlow == nullptr ? false : m_InspiratoryFlow->IsValid();
}
SEScalarVolumePerTime& SERespiratorySystem::GetInspiratoryFlow()
{
  if (m_InspiratoryFlow == nullptr)
    m_InspiratoryFlow = new SEScalarVolumePerTime();
  return *m_InspiratoryFlow;
}
double SERespiratorySystem::GetInspiratoryFlow(const VolumePerTimeUnit& unit) const
{
  if (m_InspiratoryFlow == nullptr)
    return SEScalar::dNaN();
  return m_InspiratoryFlow->GetValue(unit);
}

bool SERespiratorySystem::HasPulmonaryCompliance() const
{
  return m_PulmonaryCompliance == nullptr ? false : m_PulmonaryCompliance->IsValid();
}
SEScalarFlowCompliance& SERespiratorySystem::GetPulmonaryCompliance()
{
  if (m_PulmonaryCompliance== nullptr)
    m_PulmonaryCompliance = new SEScalarFlowCompliance();
  return *m_PulmonaryCompliance;
}
double SERespiratorySystem::GetPulmonaryCompliance(const FlowComplianceUnit& unit) const
{
  if (m_PulmonaryCompliance == nullptr)
    return SEScalar::dNaN();
  return m_PulmonaryCompliance->GetValue(unit);
}

bool SERespiratorySystem::HasPulmonaryResistance() const
{
  return m_PulmonaryResistance == nullptr ? false : m_PulmonaryResistance->IsValid();
}
SEScalarFlowResistance& SERespiratorySystem::GetPulmonaryResistance()
{
  if (m_PulmonaryResistance== nullptr)
    m_PulmonaryResistance = new SEScalarFlowResistance();
  return *m_PulmonaryResistance;
}
double SERespiratorySystem::GetPulmonaryResistance(const FlowResistanceUnit& unit) const
{
  if (m_PulmonaryResistance == nullptr)
    return SEScalar::dNaN();
  return m_PulmonaryResistance->GetValue(unit);
}

bool SERespiratorySystem::HasRespirationDriverPressure() const
{
  return m_RespirationDriverPressure == nullptr ? false : m_RespirationDriverPressure->IsValid();
}
SEScalarPressure& SERespiratorySystem::GetRespirationDriverPressure()
{
  if (m_RespirationDriverPressure == nullptr)
    m_RespirationDriverPressure = new SEScalarPressure();
  return *m_RespirationDriverPressure;
}
double SERespiratorySystem::GetRespirationDriverPressure(const PressureUnit& unit) const
{
  if (m_RespirationDriverPressure == nullptr)
    return SEScalar::dNaN();
  return m_RespirationDriverPressure->GetValue(unit);
}

bool SERespiratorySystem::HasRespirationMusclePressure() const
{
  return m_RespirationMusclePressure == nullptr ? false : m_RespirationMusclePressure->IsValid();
}
SEScalarPressure& SERespiratorySystem::GetRespirationMusclePressure()
{
  if (m_RespirationMusclePressure == nullptr)
    m_RespirationMusclePressure = new SEScalarPressure();
  return *m_RespirationMusclePressure;
}
double SERespiratorySystem::GetRespirationMusclePressure(const PressureUnit& unit) const
{
  if (m_RespirationMusclePressure == nullptr)
    return SEScalar::dNaN();
  return m_RespirationMusclePressure->GetValue(unit);
}

bool SERespiratorySystem::HasRespirationRate() const
{
  return m_RespirationRate==nullptr?false:m_RespirationRate->IsValid();
}
SEScalarFrequency& SERespiratorySystem::GetRespirationRate()
{
  if(m_RespirationRate==nullptr)
    m_RespirationRate=new SEScalarFrequency();
  return *m_RespirationRate;
}
double SERespiratorySystem::GetRespirationRate(const FrequencyUnit& unit) const
{
  if (m_RespirationRate == nullptr)
    return SEScalar::dNaN();
  return m_RespirationRate->GetValue(unit);
}

bool SERespiratorySystem::HasSpecificVentilation() const
{
  return m_SpecificVentilation == nullptr ? false : m_SpecificVentilation->IsValid();
}
SEScalar& SERespiratorySystem::GetSpecificVentilation()
{
  if (m_SpecificVentilation== nullptr)
    m_SpecificVentilation = new SEScalar();
  return *m_SpecificVentilation;
}
double SERespiratorySystem::GetSpecificVentilation() const
{
  if (m_SpecificVentilation == nullptr)
    return SEScalar::dNaN();
  return m_SpecificVentilation->GetValue();
}

bool SERespiratorySystem::HasTidalVolume() const
{
  return m_TidalVolume==nullptr?false:m_TidalVolume->IsValid();
}
SEScalarVolume& SERespiratorySystem::GetTidalVolume()
{
  if(m_TidalVolume==nullptr)
    m_TidalVolume=new SEScalarVolume();
  return *m_TidalVolume;
}
double SERespiratorySystem::GetTidalVolume(const VolumeUnit& unit) const
{
  if (m_TidalVolume == nullptr)
    return SEScalar::dNaN();
  return m_TidalVolume->GetValue(unit);
}

bool SERespiratorySystem::HasTotalAlveolarVentilation() const
{
  return m_TotalAlveolarVentilation==nullptr?false:m_TotalAlveolarVentilation->IsValid();
}
SEScalarVolumePerTime& SERespiratorySystem::GetTotalAlveolarVentilation()
{
  if(m_TotalAlveolarVentilation==nullptr)
    m_TotalAlveolarVentilation=new SEScalarVolumePerTime();
  return *m_TotalAlveolarVentilation;
}
double SERespiratorySystem::GetTotalAlveolarVentilation(const VolumePerTimeUnit& unit) const
{
  if (m_TotalAlveolarVentilation == nullptr)
    return SEScalar::dNaN();
  return m_TotalAlveolarVentilation->GetValue(unit);
}

bool SERespiratorySystem::HasTotalDeadSpaceVentilation() const
{
  return m_TotalDeadSpaceVentilation == nullptr ? false : m_TotalDeadSpaceVentilation->IsValid();
}
SEScalarVolumePerTime& SERespiratorySystem::GetTotalDeadSpaceVentilation()
{
  if (m_TotalDeadSpaceVentilation == nullptr)
    m_TotalDeadSpaceVentilation = new SEScalarVolumePerTime();
  return *m_TotalDeadSpaceVentilation;
}
double SERespiratorySystem::GetTotalDeadSpaceVentilation(const VolumePerTimeUnit& unit) const
{
  if (m_TotalDeadSpaceVentilation == nullptr)
    return SEScalar::dNaN();
  return m_TotalDeadSpaceVentilation->GetValue(unit);
}

bool SERespiratorySystem::HasTotalLungVolume() const
{
  return m_TotalLungVolume == nullptr ? false : m_TotalLungVolume->IsValid();
}
SEScalarVolume& SERespiratorySystem::GetTotalLungVolume()
{
  if (m_TotalLungVolume == nullptr)
    m_TotalLungVolume = new SEScalarVolume();
  return *m_TotalLungVolume;
}
double SERespiratorySystem::GetTotalLungVolume(const VolumeUnit& unit) const
{
  if (m_TotalLungVolume == nullptr)
    return SEScalar::dNaN();
  return m_TotalLungVolume->GetValue(unit);
}

bool SERespiratorySystem::HasTotalPulmonaryVentilation() const
{
  return m_TotalPulmonaryVentilation==nullptr?false:m_TotalPulmonaryVentilation->IsValid();
}
SEScalarVolumePerTime& SERespiratorySystem::GetTotalPulmonaryVentilation()
{
  if (m_TotalPulmonaryVentilation == nullptr)
    m_TotalPulmonaryVentilation = new SEScalarVolumePerTime();
  return *m_TotalPulmonaryVentilation;
}
double SERespiratorySystem::GetTotalPulmonaryVentilation(const VolumePerTimeUnit& unit) const
{
  if (m_TotalPulmonaryVentilation == nullptr)
    return SEScalar::dNaN();
  return m_TotalPulmonaryVentilation->GetValue(unit);
}

bool SERespiratorySystem::HasTranspulmonaryPressure() const
{
  return m_TranspulmonaryPressure == nullptr ? false : m_TranspulmonaryPressure->IsValid();
}
SEScalarPressure& SERespiratorySystem::GetTranspulmonaryPressure()
{
  if (m_TranspulmonaryPressure == nullptr)
    m_TranspulmonaryPressure = new SEScalarPressure();
  return *m_TranspulmonaryPressure;
}
double SERespiratorySystem::GetTranspulmonaryPressure(const PressureUnit& unit) const
{
  if (m_TranspulmonaryPressure == nullptr)
    return SEScalar::dNaN();
  return m_TranspulmonaryPressure->GetValue(unit);
}
