/* Distributed under the Apache License, Version 2.0.
See accompanying NOTICE file for details.*/
#include "DataRequestWidget.h"
#include "ui_DataRequest.h"

#include <QLayout>
#include <set>

#include "PulsePhysiologyEngine.h"
#include "PulseScenario.h"
#include "engine/SEEngineTracker.h"
#include "engine/SEDataRequest.h"
#include "engine/SEDataRequestManager.h"
#include "substance/SESubstance.h"
#include "substance/SESubstanceManager.h"

#include "properties/SEScalarTime.h"
#include "properties/SEScalarVolume.h"
#include "properties/SEScalarVolumePerTime.h"
#include "properties/SEScalarMassPerVolume.h"

class QDataRequestWidget::Controls : public Ui::DataRequestWidget
{
public:
  Controls(QPulse& qp) : Pulse(qp) { }
  QPulse&                            Pulse;

  QComboBox*                         SystemsBox;
  QComboBox*                         BloodChemistryBox;
  QComboBox*                         CardiovascularBox;
  QComboBox*                         DrugBox;
  QComboBox*                         EndocrineBox;
  QComboBox*                         EnergyBox;
  QComboBox*                         GastrointestinalBox;
  QComboBox*                         NervousBox;
  QComboBox*                         RenalBox;
  QComboBox*                         RespiratoryBox;
  QComboBox*                         TissueBox;

  QComboBox*                         CompartmentTypesBox;
  QComboBox*                         ChymeCmptBox;
  QComboBox*                         PulmonaryCmptBox;
  QComboBox*                         TemperatureCmptBox;
  QComboBox*                         TissueCmptBox;
  QComboBox*                         UrineCmptBox;
  QComboBox*                         VascularCmptBox;

  QComboBox*                         LiquidCmptPropsBox;
  QComboBox*                         LiquidCmptQtyPropsBox;
  QComboBox*                         GasCmptPropsBox;
  QComboBox*                         GasCmptQtyPropsBox;
  QComboBox*                         ThermalCmptPropsBox;
  QComboBox*                         TissueCmptPropsBox;

  QComboBox*                         CompartmentSubstanceTypesBox;

  QComboBox*                         SubstanceBox;
  QComboBox*                         SubstancePropsBox;

  QComboBox*                         EnvironmentBox;

  //Physiology Properties
  std::set<std::string>           BloodChemistry
                                  {
                                    "ArterialCarbonDioxidePressure",
                                    "ArterialOxygenPressure",
                                    "BloodDensity",
                                    "BloodPH",
                                    "BloodSpecificHeat",
                                    "BloodUreaNitrogenConcentration",
                                    "CarbonDioxideSaturation",
                                    "CarbonMonoxideSaturation",
                                    "Hematocrit",
                                    "HemoglobinContent",
                                    "OxygenSaturation",
                                    "Phosphate",
                                    "PlasmaVolume",
                                    "PulmonaryArterialCarbonDioxidePressure",
                                    "PulmonaryArterialOxygenPressure",
                                    "PulmonaryVenousCarbonDioxidePressure",
                                    "PulmonaryVenousOxygenPressure",
                                    "PulseOximetry",
                                    "RedBloodCellCount",
                                    "ShuntFraction",
                                    "StrongIonDifference",
                                    "TotalProteinConcentration",
                                    "VenousCarbonDioxidePressure",
                                    "VenousOxygenPressure",
                                    "VolumeFractionNeutralPhospholipidInPlasma",
                                    "VolumeFractionNeutralLipidInPlasma",
                                    "WhiteBloodCellCount"
                                  };
  std::set<std::string>           Cardiovascular
                                  {
                                    "ArterialPressure",
                                    "BloodVolume",
                                    "CardiacIndex",
                                    "CardiacOutput",
                                    "CentralVenousPressure",
                                    "CerebralBloodFlow",
                                    "CerebralPerfusionPressure",
                                    "DiastolicArterialPressure",
                                    "HeartEjectionFraction",
                                    "HeartRate",
                                    //"HeartRhythm",
                                    "HeartStrokeVolume",
                                    "IntracranialPressure",
                                    "MeanArterialCarbonDioxidePartialPressure",
                                    "MeanArterialCarbonDioxidePartialPressureDelta",
                                    "MeanArterialPressure",
                                    "MeanCentralVenousPressure",
                                    "MeanSkinFlow",
                                    "PulmonaryArterialPressure",
                                    "PulmonaryCapillariesWedgePressure",
                                    "PulmonaryDiastolicArterialPressure",
                                    "PulmonaryMeanArterialPressure",
                                    "PulmonaryMeanCapillaryFlow",
                                    "PulmonaryMeanShuntFlow",
                                    "PulmonarySystolicArterialPressure",
                                    "PulmonaryVascularResistance",
                                    "PulmonaryVascularResistanceIndex",
                                    "PulsePressure",
                                    "SystolicArterialPressure",
                                    "SystemicVascularResistance"
                                  };
  std::set<std::string>           Drug
                                  {
                                    "BronchodilationLevel",
                                    "HeartRateChange",
                                    "MeanBloodPressureChange",
                                    "NeuromuscularBlockLevel",
                                    "PulsePressureChange",
                                    "PupillaryResponse",
                                    "RespirationRateChange",
                                    "SedationLevel",
                                    "TidalVolumeChange",
                                    "TubularPermeabilityChange"
                                  };
  std::set<std::string>           Endocrine
                                  {
                                    "InsulinSynthesisRate"
                                  };
  std::set<std::string>           Energy
                                  {
                                    "AchievedExerciseLevel",
                                    "CreatinineProductionRate",
                                    "CoreTemperature",
                                    "ExerciseMeanArterialPressureDelta",
                                    "FatigueLevel",
                                    "KetoneProductionRate",
                                    "LactateProductionRate",
                                    "SkinTemperature",
                                    "SweatRate",
                                    "TotalMetabolicRate",
                                    "TotalWorkRateLevel"
                                  };
  std::set<std::string>           Gastrointestinal
                                  {
                                    "ChymeAbsorptionRate"//,
                                    //"StomachContents"
                                  };
  std::set<std::string>           Nervous
                                  {
                                    "BaroreceptorComplianceScale",
                                    "BaroreceptorHeartElastanceScale",
                                    "BaroreceptorHeartRateScale",
                                    "BaroreceptorResistanceScale",
                                    "ChemoreceptorHeartElastanceScale",
                                    "ChemoreceptorHeartRateScale",
                                    "LeftEyePupillaryResponse",
                                    "RightEyePupillaryResponse"
                                  };
  std::set<std::string>           Renal
                                  {
                                    "FiltrationFraction",
                                    "GlomerularFiltrationRate",
                                    "LeftAfferentArterioleResistance",
                                    "LeftBowmansCapsulesHydrostaticPressure",
                                    "LeftBowmansCapsulesOsmoticPressure",
                                    "LeftEfferentArterioleResistance",
                                    "LeftFiltrationFraction",
                                    "LeftGlomerularCapillariesHydrostaticPressure",
                                    "LeftGlomerularCapillariesOsmoticPressure",
                                    "LeftGlomerularFiltrationCoefficient",
                                    "LeftGlomerularFiltrationRate",
                                    "LeftGlomerularFiltrationSurfaceArea",
                                    "LeftGlomerularFluidPermeability",
                                    "LeftNetFiltrationPressure",
                                    "LeftNetReabsorptionPressure",
                                    "LeftPeritubularCapillariesHydrostaticPressure",
                                    "LeftPeritubularCapillariesOsmoticPressure",
                                    "LeftReabsorptionFiltrationCoefficient",
                                    "LeftReabsorptionRate",
                                    "LeftTubularHydrostaticPressure",
                                    "LeftTubularOsmoticPressure",
                                    "LeftTubularReabsorptionFiltrationSurfaceArea",
                                    "LeftTubularReabsorptionFluidPermeability",
                                    "RenalBloodFlow",
                                    "RenalPlasmaFlow",
                                    "RenalVascularResistance",
                                    "RightAfferentArterioleResistance",
                                    "RightBowmansCapsulesHydrostaticPressure",
                                    "RightBowmansCapsulesOsmoticPressure",
                                    "RightEfferentArterioleResistance",
                                    "RightFiltrationFraction",
                                    "RightGlomerularFiltrationRate",
                                    "RightGlomerularCapillariesHydrostaticPressure",
                                    "RightGlomerularCapillariesOsmoticPressure",
                                    "RightGlomerularFiltrationCoefficient",
                                    "RightGlomerularFiltrationSurfaceArea",
                                    "RightGlomerularFluidPermeability",
                                    "RightPeritubularCapillariesHydrostaticPressure",
                                    "RightPeritubularCapillariesOsmoticPressure",
                                    "RightNetFiltrationPressure",
                                    "RightNetReabsorptionPressure",
                                    "RightReabsorptionFiltrationCoefficient",
                                    "RightReabsorptionRate",
                                    "RightTubularHydrostaticPressure",
                                    "RightTubularOsmoticPressure",
                                    "RightTubularReabsorptionFiltrationSurfaceArea",
                                    "RightTubularReabsorptionFluidPermeability",
                                    "UrinationRate",
                                    "UrineOsmolality",
                                    "UrineOsmolarity",
                                    "UrineProductionRate",
                                    "UrineSpecificGravity",
                                    "UrineUreaNitrogenConcentration",
                                    "UrineVolume"
                                  };
  std::set<std::string>           Respiratory
                                  {
                                    "AlveolarArterialGradient",
                                    "CarricoIndex",
                                    "EndTidalCarbonDioxideFraction",
                                    "EndTidalCarbonDioxidePressure",
                                    "ExpiratoryFlow",
                                    "InspiratoryExpiratoryRatio",
                                    "InspiratoryFlow",
                                    "PulmonaryCompliance",
                                    "PulmonaryResistance",
                                    "RespirationDriverPressure",
                                    "RespirationMusclePressure",
                                    "RespirationRate",
                                    "SpecificVentilation",
                                    "TidalVolume",
                                    "TotalAlveolarVentilation",
                                    "TotalDeadSpaceVentilation",
                                    "TotalPulmonaryVentilation",
                                    "TotalLungVolume",
                                    "TranspulmonaryPressure"
                                  };
  std::set<std::string>           Tissue
                                  {
                                    "CarbonDioxideProductionRate",
                                    "ExtracellularFluidVolume",
                                    "ExtravascularFluidVolume",
                                    "IntracellularFluidPH",
                                    "IntracellularFluidVolume",
                                    "OxygenConsumptionRate",
                                    "RespiratoryExchangeRatio"
                                  };
};

void Format(std::set<std::string>& set)
{
  std::vector<QString> qStrings;
  for (std::string s : set)
    qStrings.push_back(QString::fromStdString(s.c_str()));

  set.clear();
  std::stringstream ss;
  for (QString s : qStrings)
  {
    ss.str("");
    QStringList slist = s.split(QRegExp("(?=[A-Z])"), QString::SkipEmptyParts);
    for (auto itr=slist.begin(); itr!=slist.end(); ++itr)
    {
      ss << (*itr).toStdString();
      if (itr + 1 != slist.end() && ( (*itr).length() > 1 || (*(itr + 1)).length() > 1 ))
        ss << " ";
    }
    set.insert(ss.str());
  }
}

std::string RemoveSpacing(QString str)
{
  str = str.simplified();
  str.replace(" ", "");
  return str.toStdString();
}

QDataRequestWidget::QDataRequestWidget(QPulse& qp, QWidget *parent, Qt::WindowFlags flags) : QDockWidget(parent,flags)
{
  m_Controls = new Controls(qp); 
  m_Controls->setupUi(this);

  QFont font;
  font.setPointSize(11);

  Format(m_Controls->BloodChemistry);
  Format(m_Controls->Cardiovascular);
  Format(m_Controls->Drug);
  Format(m_Controls->Endocrine);
  Format(m_Controls->Energy);
  Format(m_Controls->Gastrointestinal);
  Format(m_Controls->Nervous);
  Format(m_Controls->Renal);
  Format(m_Controls->Respiratory);
  Format(m_Controls->Tissue);

  m_Controls->CategoryBox->addItem("Physiology");
  m_Controls->CategoryBox->addItem("Anatomy");
  m_Controls->CategoryBox->addItem("Substance");
  m_Controls->CategoryBox->addItem("Anatomy Substance");
  m_Controls->CategoryBox->addItem("Environment");
  //m_Controls->CategoryBox->setMaximumWidth(275);
  m_Controls->CategoryBox->setFont(font);
  connect(m_Controls->CategoryBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->SystemsBox = new QComboBox(this);
  m_Controls->SystemsBox->addItem("Blood Chemistry");
  m_Controls->SystemsBox->addItem("Cardiovascular");
  m_Controls->SystemsBox->addItem("Drug");
  m_Controls->SystemsBox->addItem("Endocrine");
  m_Controls->SystemsBox->addItem("Energy");
  m_Controls->SystemsBox->addItem("Gastrointestinal");
  m_Controls->SystemsBox->addItem("Nervous");
  m_Controls->SystemsBox->addItem("Renal");
  m_Controls->SystemsBox->addItem("Respiratory");
  m_Controls->SystemsBox->addItem("Tissue");
  m_Controls->SystemsBox->setFont(font);
  connect(m_Controls->SystemsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->BloodChemistryBox = new QComboBox(this);
  for(std::string s : m_Controls->BloodChemistry)
    m_Controls->BloodChemistryBox->addItem(s.c_str());
  m_Controls->BloodChemistryBox->setFont(font);
  connect(m_Controls->BloodChemistryBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->CardiovascularBox = new QComboBox(this);
  for (std::string s : m_Controls->Cardiovascular)
    m_Controls->CardiovascularBox->addItem(s.c_str());
  m_Controls->CardiovascularBox->setFont(font);
  connect(m_Controls->CardiovascularBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->DrugBox = new QComboBox(this);
  for (std::string s : m_Controls->Drug)
    m_Controls->DrugBox->addItem(s.c_str());
  m_Controls->DrugBox->setFont(font);
  connect(m_Controls->DrugBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->EndocrineBox = new QComboBox(this);
  for (std::string s : m_Controls->Endocrine)
    m_Controls->EndocrineBox->addItem(s.c_str());
  m_Controls->EndocrineBox->setFont(font);
  connect(m_Controls->EndocrineBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->EnergyBox = new QComboBox(this);
  for (std::string s : m_Controls->Energy)
    m_Controls->EnergyBox->addItem(s.c_str());
  m_Controls->EnergyBox->setFont(font);
  connect(m_Controls->EnergyBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->GastrointestinalBox = new QComboBox(this);
  for (std::string s : m_Controls->Gastrointestinal)
    m_Controls->GastrointestinalBox->addItem(s.c_str());
  m_Controls->GastrointestinalBox->setFont(font);
  connect(m_Controls->GastrointestinalBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->NervousBox = new QComboBox(this);
  for (std::string s : m_Controls->Nervous)
    m_Controls->NervousBox->addItem(s.c_str());
  m_Controls->NervousBox->setFont(font);
  connect(m_Controls->NervousBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->RenalBox = new QComboBox(this);
  for (std::string s : m_Controls->Renal)
    m_Controls->RenalBox->addItem(s.c_str());
  m_Controls->RenalBox->setFont(font);
  connect(m_Controls->RenalBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->RespiratoryBox = new QComboBox(this);
  for (std::string s : m_Controls->Respiratory)
    m_Controls->RespiratoryBox->addItem(s.c_str());
  m_Controls->RespiratoryBox->setFont(font);
  connect(m_Controls->RespiratoryBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->TissueBox = new QComboBox(this);
  for (std::string s : m_Controls->Tissue)
    m_Controls->TissueBox->addItem(s.c_str());
  m_Controls->TissueBox->setFont(font);
  connect(m_Controls->TissueBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->CompartmentTypesBox = new QComboBox(this);
  m_Controls->CompartmentTypesBox->addItem("Chyme");
  m_Controls->CompartmentTypesBox->addItem("Extracellular");
  m_Controls->CompartmentTypesBox->addItem("Intracellular");
  m_Controls->CompartmentTypesBox->addItem("Pulmonary");
  m_Controls->CompartmentTypesBox->addItem("Temperature");
  m_Controls->CompartmentTypesBox->addItem("Tissue");
  m_Controls->CompartmentTypesBox->addItem("Urine");
  m_Controls->CompartmentTypesBox->addItem("Vascular");
  m_Controls->CompartmentTypesBox->setFont(font);
  connect(m_Controls->CompartmentTypesBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->CompartmentSubstanceTypesBox = new QComboBox(this);
  m_Controls->CompartmentSubstanceTypesBox->addItem("Chyme");
  m_Controls->CompartmentSubstanceTypesBox->addItem("Extracellular");
  m_Controls->CompartmentSubstanceTypesBox->addItem("Intracellular");
  m_Controls->CompartmentSubstanceTypesBox->addItem("Pulmonary");
  m_Controls->CompartmentSubstanceTypesBox->addItem("Urine");
  m_Controls->CompartmentSubstanceTypesBox->addItem("Vascular");
  m_Controls->CompartmentSubstanceTypesBox->setFont(font);
  connect(m_Controls->CompartmentSubstanceTypesBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->ChymeCmptBox = new QComboBox(this);
  for (std::string s : pulse::ChymeCompartment::GetValues())
    m_Controls->ChymeCmptBox->addItem(s.c_str());
  m_Controls->ChymeCmptBox->setFont(font);
  connect(m_Controls->ChymeCmptBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->PulmonaryCmptBox = new QComboBox(this);
  for (std::string s : pulse::PulmonaryCompartment::GetValues())
    m_Controls->PulmonaryCmptBox->addItem(s.c_str());
  m_Controls->PulmonaryCmptBox->setFont(font);
  connect(m_Controls->PulmonaryCmptBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->TemperatureCmptBox = new QComboBox(this);
  for (std::string s : pulse::TemperatureCompartment::GetValues())
    m_Controls->TemperatureCmptBox->addItem(s.c_str());
  m_Controls->TemperatureCmptBox->setFont(font);
  connect(m_Controls->TemperatureCmptBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));
m_Controls->TissueCmptBox = new QComboBox(this);
  for (std::string s : pulse::TissueCompartment::GetValues())
    m_Controls->TissueCmptBox->addItem(s.c_str());
  m_Controls->TissueCmptBox->setFont(font);
  connect(m_Controls->TissueCmptBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->UrineCmptBox = new QComboBox(this);
  for (std::string s : pulse::UrineCompartment::GetValues())
    m_Controls->UrineCmptBox->addItem(s.c_str());
  m_Controls->UrineCmptBox->setFont(font);
  connect(m_Controls->UrineCmptBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->VascularCmptBox = new QComboBox(this);
  for (std::string s : pulse::VascularCompartment::GetValues())
    m_Controls->VascularCmptBox->addItem(s.c_str());
  m_Controls->VascularCmptBox->setFont(font);
  connect(m_Controls->VascularCmptBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->LiquidCmptPropsBox = new QComboBox(this);
  m_Controls->LiquidCmptPropsBox->addItem("In Flow");
  m_Controls->LiquidCmptPropsBox->addItem("Out Flow");
  m_Controls->LiquidCmptPropsBox->addItem("Pressure");
  m_Controls->LiquidCmptPropsBox->addItem("Volume");
  m_Controls->LiquidCmptPropsBox->addItem("Water Volume Fraction");
  m_Controls->LiquidCmptPropsBox->addItem("PH");
  m_Controls->LiquidCmptPropsBox->setFont(font);
  connect(m_Controls->LiquidCmptPropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->LiquidCmptQtyPropsBox = new QComboBox(this);
  m_Controls->LiquidCmptQtyPropsBox->addItem("Concentration");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Mass");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Mass Cleared");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Mass Deposited");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Mass Excreted");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Molarity");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Partial Pressure");
  m_Controls->LiquidCmptQtyPropsBox->addItem("Saturation");
  m_Controls->LiquidCmptQtyPropsBox->setFont(font);
  connect(m_Controls->LiquidCmptQtyPropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->GasCmptPropsBox = new QComboBox(this);
  m_Controls->GasCmptPropsBox->addItem("In Flow");
  m_Controls->GasCmptPropsBox->addItem("Out Flow");
  m_Controls->GasCmptPropsBox->addItem("Pressure");
  m_Controls->GasCmptPropsBox->addItem("Volume");
  m_Controls->GasCmptPropsBox->setFont(font);
  connect(m_Controls->GasCmptPropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->GasCmptQtyPropsBox = new QComboBox(this);
  m_Controls->GasCmptQtyPropsBox->addItem("Partial Pressure");
  m_Controls->GasCmptQtyPropsBox->addItem("Volume");
  m_Controls->GasCmptQtyPropsBox->addItem("Volume Fraction");
  m_Controls->GasCmptQtyPropsBox->setFont(font);
  connect(m_Controls->GasCmptQtyPropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->ThermalCmptPropsBox = new QComboBox(this);
  m_Controls->ThermalCmptPropsBox->addItem("Heat Transfer Rate In");
  m_Controls->ThermalCmptPropsBox->addItem("Heat Transfer Rate Out");
  m_Controls->ThermalCmptPropsBox->addItem("Heat");
  m_Controls->ThermalCmptPropsBox->addItem("Temperature");
  m_Controls->ThermalCmptPropsBox->setFont(font);
  connect(m_Controls->ThermalCmptPropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->TissueCmptPropsBox = new QComboBox(this);
  m_Controls->TissueCmptPropsBox->addItem("Acidic Phospohlipid Concentration");
  m_Controls->TissueCmptPropsBox->addItem("Matrix Volume");
  m_Controls->TissueCmptPropsBox->addItem("Neutral Lipids Volume Fraction");
  m_Controls->TissueCmptPropsBox->addItem("Neutral Phospholipids Volume Fraction");
  m_Controls->TissueCmptPropsBox->addItem("Tissue To Plasma Albumin Ratio");
  m_Controls->TissueCmptPropsBox->addItem("Tissue  To Plasma Alpha Acid Glycoprotein Ratio");
  m_Controls->TissueCmptPropsBox->addItem("Tissue To Plasma Lipoprotein Ratio");
  m_Controls->TissueCmptPropsBox->addItem("Total Mass");
  m_Controls->TissueCmptPropsBox->setFont(font);
  connect(m_Controls->TissueCmptPropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->SubstanceBox = new QComboBox(this);
  for (SESubstance* s : qp.GetScenario().GetSubstanceManager().GetSubstances())
    m_Controls->SubstanceBox->addItem(s->GetName().c_str());
  m_Controls->SubstanceBox->setFont(font);
  connect(m_Controls->SubstanceBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->SubstancePropsBox = new QComboBox(this);
  m_Controls->SubstancePropsBox->addItem("Alveolar Transfer");
  m_Controls->SubstancePropsBox->addItem("Blood Concentration");
  m_Controls->SubstancePropsBox->addItem("Mass In Body");
  m_Controls->SubstancePropsBox->addItem("Mass In Blood");
  m_Controls->SubstancePropsBox->addItem("Mass In Tissue");
  m_Controls->SubstancePropsBox->addItem("Plasma Concentration");
  m_Controls->SubstancePropsBox->addItem("Systemic Mass Cleared");
  m_Controls->SubstancePropsBox->addItem("Tissue Concentration");
  m_Controls->SubstancePropsBox->setFont(font);
  connect(m_Controls->SubstancePropsBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  m_Controls->EnvironmentBox = new QComboBox(this);
  m_Controls->EnvironmentBox->addItem("Convective Heat Loss");
  m_Controls->EnvironmentBox->addItem("Convective Heat Tranfer Coefficient");
  m_Controls->EnvironmentBox->addItem("Evaporative Heat Loss");
  m_Controls->EnvironmentBox->addItem("Evaporative Heat Tranfer Coefficient");
  m_Controls->EnvironmentBox->addItem("Radiative Heat Loss");
  m_Controls->EnvironmentBox->addItem("Radiative Heat Tranfer Coefficient");
  m_Controls->EnvironmentBox->addItem("Respiration Heat Loss");
  m_Controls->EnvironmentBox->addItem("Skin Heat Loss");
  m_Controls->EnvironmentBox->setFont(font);
  connect(m_Controls->EnvironmentBox, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSelectionBoxes()));

  UpdateSelectionBoxes();
}

QDataRequestWidget::~QDataRequestWidget()
{
  // TODO clean up everything we allocated in the ctor
  delete m_Controls;
}

void QDataRequestWidget::UpdateSelectionBoxes()
{
  // First let's remove everything
  QLayoutItem* item;
  while ((item = m_Controls->Selections->layout()->takeAt(0)) != nullptr)
    m_Controls->Selections->layout()->removeWidget(item->widget());
  // Hide All Systems
  m_Controls->SystemsBox->hide();
  {
    m_Controls->BloodChemistryBox->hide();
    m_Controls->CardiovascularBox->hide();
    m_Controls->DrugBox->hide();
    m_Controls->EndocrineBox->hide();
    m_Controls->EnergyBox->hide();
    m_Controls->GastrointestinalBox->hide();
    m_Controls->NervousBox->hide();
    m_Controls->RenalBox->hide();
    m_Controls->RespiratoryBox->hide();
    m_Controls->TissueBox->hide();
  }
  m_Controls->CompartmentTypesBox->hide();
  {
    m_Controls->ChymeCmptBox->hide();
    m_Controls->PulmonaryCmptBox->hide();
    m_Controls->TemperatureCmptBox->hide();
    m_Controls->TissueCmptBox->hide();
    m_Controls->UrineCmptBox->hide();
    m_Controls->VascularCmptBox->hide();

    m_Controls->GasCmptPropsBox->hide();
    m_Controls->GasCmptQtyPropsBox->hide();
    m_Controls->LiquidCmptPropsBox->hide();
    m_Controls->LiquidCmptQtyPropsBox->hide();
    m_Controls->ThermalCmptPropsBox->hide();
    m_Controls->TissueCmptPropsBox->hide();
  }
  m_Controls->SubstanceBox->hide();
  m_Controls->SubstancePropsBox->hide();
  m_Controls->CompartmentSubstanceTypesBox->hide();
  m_Controls->EnvironmentBox->hide();
  
  m_Controls->Selections->layout()->addWidget(m_Controls->CategoryBox);
  
  switch (m_Controls->CategoryBox->currentIndex())
  {
  case 0:// Physiology
  {
    m_Controls->Selections->layout()->addWidget(m_Controls->SystemsBox);
    m_Controls->SystemsBox->show();
    switch (m_Controls->SystemsBox->currentIndex())
    {
    case 0: // Blood Chemistry
      m_Controls->Selections->layout()->addWidget(m_Controls->BloodChemistryBox);
      m_Controls->BloodChemistryBox->show();
      // TODO Units Box
      break;
    case 1: // Cardiovascular
      m_Controls->Selections->layout()->addWidget(m_Controls->CardiovascularBox);
      m_Controls->CardiovascularBox->show();
      // TODO Units Box
      break;
    case 2: // Drug
      m_Controls->Selections->layout()->addWidget(m_Controls->DrugBox);
      m_Controls->DrugBox->show();
      // TODO Units Box
      break;
    case 3: // Endocrine
      m_Controls->Selections->layout()->addWidget(m_Controls->EndocrineBox);
      m_Controls->EndocrineBox->show();
      // TODO Units Box
      break;
    case 4: // Energy
      m_Controls->Selections->layout()->addWidget(m_Controls->EnergyBox);
      m_Controls->EnergyBox->show();
      // TODO Units Box
      break;
    case 5:// Gastrointestinal
      m_Controls->Selections->layout()->addWidget(m_Controls->GastrointestinalBox);
      m_Controls->GastrointestinalBox->show();
      // TODO Units Box
      break;
    case 6: // Nervous
      m_Controls->Selections->layout()->addWidget(m_Controls->NervousBox);
      m_Controls->NervousBox->show();
      // TODO Units Box
      break;
    case 7: // Renal
      m_Controls->Selections->layout()->addWidget(m_Controls->RenalBox);
      m_Controls->RenalBox->show();
      // TODO Units Box
      break;
    case 8: // Respiration
      m_Controls->Selections->layout()->addWidget(m_Controls->RespiratoryBox);
      m_Controls->RespiratoryBox->show();
      // TODO Units Box
      break;
    case 9: // Tissue
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueBox);
      m_Controls->TissueBox->show();
      // TODO Units Box
      break;
    }
    // TODO activate the unit box associated with the active system box property
    break;
  }
  case 1:// Anatomy
  {
    m_Controls->Selections->layout()->addWidget(m_Controls->CompartmentTypesBox);
    m_Controls->CompartmentTypesBox->show();
    switch (m_Controls->CompartmentTypesBox->currentIndex())
    {
    case 0: // Chyme
      m_Controls->Selections->layout()->addWidget(m_Controls->ChymeCmptBox);
      m_Controls->ChymeCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptPropsBox);
      m_Controls->LiquidCmptPropsBox->show();
      // TODO Units Box
      break;
    case 1: // Extracellular
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueCmptBox);
      m_Controls->TissueCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptPropsBox);
      m_Controls->LiquidCmptPropsBox->show();
      // TODO Units Box
      break;
    case 2: // Intracellular
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueCmptBox);
      m_Controls->TissueCmptBox->show(); 
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptPropsBox);
      m_Controls->LiquidCmptPropsBox->show();
      // TODO Units Box
      break;
    case 3: // Pulmonary
      m_Controls->Selections->layout()->addWidget(m_Controls->PulmonaryCmptBox);
      m_Controls->PulmonaryCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->GasCmptPropsBox);
      m_Controls->GasCmptPropsBox->show();
      // TODO Units Box
      break;
    case 4: // Temperature
      m_Controls->Selections->layout()->addWidget(m_Controls->TemperatureCmptBox);
      m_Controls->TemperatureCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->ThermalCmptPropsBox);
      m_Controls->ThermalCmptPropsBox->show();
      // TODO Units Box
      break;
    case 5: // Tissue
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueCmptBox);
      m_Controls->TissueCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueCmptPropsBox);
      m_Controls->TissueCmptPropsBox->show();
      // TODO Units Box
      break;
    case 6: // Urine
      m_Controls->Selections->layout()->addWidget(m_Controls->UrineCmptBox);
      m_Controls->UrineCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptPropsBox);
      m_Controls->LiquidCmptPropsBox->show();
      // TODO Units Box
      break;
    case 7: // Vascular
      m_Controls->Selections->layout()->addWidget(m_Controls->VascularCmptBox);
      m_Controls->VascularCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptPropsBox);
      m_Controls->LiquidCmptPropsBox->show();
      // TODO Units Box
      break;
    }
    break;
  }
  case 2:// Substance
  {
    m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);
    m_Controls->SubstanceBox->show();
    m_Controls->Selections->layout()->addWidget(m_Controls->SubstancePropsBox);
    m_Controls->SubstancePropsBox->show();
    // TODO Units Box
    break;
  }
  case 3:// Anatomy Substance
  {
    m_Controls->Selections->layout()->addWidget(m_Controls->CompartmentSubstanceTypesBox);
    m_Controls->CompartmentSubstanceTypesBox->show();
    switch (m_Controls->CompartmentSubstanceTypesBox->currentIndex())
    {
    case 0: // Chyme
      m_Controls->Selections->layout()->addWidget(m_Controls->ChymeCmptBox);
      m_Controls->ChymeCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);
      m_Controls->SubstanceBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptQtyPropsBox);
      m_Controls->LiquidCmptQtyPropsBox->show();
      // TODO Units Box
      break;
    case 1: // Extracellular
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueCmptBox);
      m_Controls->TissueCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);
      m_Controls->SubstanceBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptQtyPropsBox);
      m_Controls->LiquidCmptQtyPropsBox->show();
      // TODO Units Box
      break;
    case 2: // Intracellular
      m_Controls->Selections->layout()->addWidget(m_Controls->TissueCmptBox);
      m_Controls->TissueCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);
      m_Controls->SubstanceBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptQtyPropsBox);
      m_Controls->LiquidCmptQtyPropsBox->show();
      // TODO Units Box
      break;
    case 3: // Pulmonary
      m_Controls->Selections->layout()->addWidget(m_Controls->PulmonaryCmptBox);
      m_Controls->PulmonaryCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);// TODO This should be Gas substances only!!!
      m_Controls->SubstanceBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->GasCmptQtyPropsBox);
      m_Controls->GasCmptQtyPropsBox->show();
      // TODO Units Box
      break;
    case 4: // Urine
      m_Controls->Selections->layout()->addWidget(m_Controls->UrineCmptBox);
      m_Controls->UrineCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);
      m_Controls->SubstanceBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptQtyPropsBox);
      m_Controls->LiquidCmptQtyPropsBox->show();
      // TODO Units Box
      break;
    case 5: // Vascular
      m_Controls->Selections->layout()->addWidget(m_Controls->VascularCmptBox);
      m_Controls->VascularCmptBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->SubstanceBox);
      m_Controls->SubstanceBox->show();
      m_Controls->Selections->layout()->addWidget(m_Controls->LiquidCmptQtyPropsBox);
      m_Controls->LiquidCmptQtyPropsBox->show();
      // TODO Units Box
      break;
    }
    break;
  }
  case 4:// Environment
  {
    m_Controls->Selections->layout()->addWidget(m_Controls->EnvironmentBox);
    m_Controls->EnvironmentBox->show();
    // TODO Units Box
    break;
  }
  default:
  {
    m_Controls->Pulse.GetEngine().GetLogger()->Error("Unsupported Data Request category");
  }
  }
}

SEDataRequest& QDataRequestWidget::GetDataRequest(SEDataRequestManager& drMgr)
{
  QString prop;
  QString cmpt;
  QString subs;
  std::string substance;

  switch (m_Controls->CategoryBox->currentIndex())
  {
  case 0:// Physiology
    switch (m_Controls->SystemsBox->currentIndex())
    {
    case 0: // Blood Chemistry
      prop = m_Controls->BloodChemistryBox->currentText();
      // TODO Units Box
       return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 1: // Cardiovascular
      prop = m_Controls->CardiovascularBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 2: // Drug
      prop = m_Controls->DrugBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 3: // Endocrine
      prop = m_Controls->EndocrineBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 4: // Energy
      prop = m_Controls->EnergyBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 5:// Gastrointestinal
      prop = m_Controls->GastrointestinalBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 6: // Nervous
      prop = m_Controls->NervousBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 7: // Renal
      prop = m_Controls->RenalBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 8: // Respiration
      prop = m_Controls->RespiratoryBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    case 9: // Tissue
      prop = m_Controls->TissueBox->currentText();
      // TODO Units Box
      return drMgr.CreatePhysiologyDataRequest(RemoveSpacing(prop));
    }
  case 1://Anatomy
    prop = m_Controls->LiquidCmptPropsBox->currentText();
    switch (m_Controls->CompartmentTypesBox->currentIndex())
    {
    case 0: // Chyme
      cmpt = m_Controls->ChymeCmptBox->currentText();
      return drMgr.CreateLiquidCompartmentDataRequest(RemoveSpacing(cmpt),RemoveSpacing(prop));
      break;
    case 1: // Extracellular
      cmpt = m_Controls->TissueCmptBox->currentText();
      // TODO Units Box
      return drMgr.CreateLiquidCompartmentDataRequest(RemoveSpacing(cmpt),RemoveSpacing(prop));
    case 2: // Intracellular
      // TODO Units Box
      return drMgr.CreateLiquidCompartmentDataRequest(RemoveSpacing(cmpt), RemoveSpacing(prop));
    case 3: // Pulmonary
      cmpt = m_Controls->PulmonaryCmptBox->currentText();
      prop = m_Controls->GasCmptPropsBox->currentText();
      return drMgr.CreateGasCompartmentDataRequest(RemoveSpacing(cmpt),RemoveSpacing(prop));
      // TODO Units Box
      break;
    case 4: // Temperature
      // TODO Units Box
      prop = m_Controls->ThermalCmptPropsBox->currentText();
      cmpt = m_Controls->TemperatureCmptBox->currentText();
      return drMgr.CreateThermalCompartmentDataRequest(RemoveSpacing(cmpt),RemoveSpacing(prop));
    case 5: // Tissue
      // TODO Units Box
      cmpt = m_Controls->TissueCmptBox->currentText();
      prop = m_Controls->TissueCmptPropsBox->currentText();
      return drMgr.CreateTissueCompartmentDataRequest(RemoveSpacing(cmpt), RemoveSpacing(prop));
    case 6: // Urine
      // TODO Units Box
      cmpt = m_Controls->UrineCmptBox->currentText();
      return drMgr.CreateLiquidCompartmentDataRequest(RemoveSpacing(cmpt),RemoveSpacing(prop));
      break;
    case 7: // Vascular
      // TODO Units Box
      cmpt = m_Controls->VascularCmptBox->currentText();
      return drMgr.CreateLiquidCompartmentDataRequest(RemoveSpacing(cmpt),RemoveSpacing(prop));
      break;
    }
  case 2://Substance
    subs = m_Controls->SubstanceBox->currentText();
    prop = m_Controls->SubstancePropsBox->currentText();
    substance = RemoveSpacing(subs);
    if(prop == "Plasma Concentration")
      return drMgr.CreateSubstanceDataRequest(substance, RemoveSpacing(prop), MassPerVolumeUnit::ug_Per_mL);
    return drMgr.CreateSubstanceDataRequest(substance,RemoveSpacing(prop));
  case 3://Anatomy Substance
    subs = m_Controls->SubstanceBox->currentText();
    substance = RemoveSpacing(subs);
    prop = m_Controls->LiquidCmptQtyPropsBox->currentText();
    switch (m_Controls->CompartmentSubstanceTypesBox->currentIndex())
    {
    case 0: // Chyme
      cmpt = m_Controls->ChymeCmptBox->currentText();
      break;
    case 1: // Extracellular
      //cmpt = m_Controls->TissueCmptBox->currentText();
      // TODO Units Box
      break;
    case 2: // Intracellular
      // TODO Units Box
      /*cmpt = m_Controls->TissueCmptBox->currentText();*/
      break;
    case 3: // Pulmonary
      cmpt = m_Controls->PulmonaryCmptBox->currentText();
      prop = m_Controls->GasCmptQtyPropsBox->currentText();
      return drMgr.CreateGasCompartmentDataRequest(RemoveSpacing(cmpt),substance,RemoveSpacing(prop));
      // TODO Units Box
      break;
    case 4: // Urine
      // TODO Units Box
      cmpt = m_Controls->UrineCmptBox->currentText();
      break;
    case 5: // Vascular
      // TODO Units Box
      cmpt = m_Controls->VascularCmptBox->currentText();
      break;
    }   
    return drMgr.CreateLiquidCompartmentDataRequest(RemoveSpacing(cmpt), substance,RemoveSpacing(prop));

  case 4://Environment
    prop = m_Controls->EnvironmentBox->currentText();
    return drMgr.CreateEnvironmentDataRequest(RemoveSpacing(prop));
  default:
    m_Controls->Pulse.GetEngine().GetLogger()->Error("Unsupported Data Request category");
    return drMgr.CreateDataRequest(eDataRequest_Category::Patient);
  }

}
