/* Distributed under the Apache License, Version 2.0.
See accompanying NOTICE file for details.*/
#include "PatientEditorWidget.h"
#include "ui_PatientEditor.h"
#include "QPulse.h"
#include <QLineEdit>
#include <QFileDialog>
#include <QMessageBox>
#include "controls/ScalarWidget.h"
#include "controls/ScalarQuantityWidget.h"

#include "cdm/CommonDataModel.h"
#include "cdm/PhysiologyEngine.h"
#include "cdm/utils/FileUtils.h"
#include "cdm/engine/SEPatientConfiguration.h"
#include "cdm/patient/SEPatient.h"
#include "cdm/properties/SEScalar0To1.h"
#include "cdm/properties/SEScalarArea.h"
#include "cdm/properties/SEScalarFrequency.h"
#include "cdm/properties/SEScalarLength.h"
#include "cdm/properties/SEScalarMass.h"
#include "cdm/properties/SEScalarMassPerVolume.h"
#include "cdm/properties/SEScalarPower.h"
#include "cdm/properties/SEScalarPressure.h"
#include "cdm/properties/SEScalarTime.h"
#include "cdm/properties/SEScalarVolume.h"

class QPatientEditorWidget::Controls : public Ui::PatientEditorWidget
{
public:
  Controls(QPulse& qp) : Pulse(qp) {}
  QPulse&                Pulse;

  std::string                               StateLocation;

  QWidget*                                  Name;
  QLabel*                                   NameLabel;
  QSpacerItem*                              NameSpacer;
  QLineEdit*                                NameValue;
  QHBoxLayout*                              NameLayout;

  QWidget*                                  Sex;
  QLabel*                                   SexLabel;
  QSpacerItem*                              SexSpacer;
  QComboBox*                                SexValue;
  QHBoxLayout*                              SexLayout;

  QScalarQuantityWidget<TimeUnit>*          Age;
  QScalarQuantityWidget<MassUnit>*          Weight;
  QScalarQuantityWidget<LengthUnit>*        Height;
  QScalarQuantityWidget<MassPerVolumeUnit>* BodyDensity;
  QScalarWidget*                            BodyFatFraction;
  QScalarQuantityWidget<MassUnit>*          LeanBodyMass;
  QScalarQuantityWidget<AreaUnit>*          SkinSurfaceArea;
  QScalarQuantityWidget<PowerUnit>*         BasalMetabolicRate;

  QScalarQuantityWidget<AreaUnit>*          AlveoliSurfaceArea;
  QScalarWidget*                            RightLungRatio;
  QScalarQuantityWidget<FrequencyUnit>*     RespirationRateBaseline;
  QScalarQuantityWidget<VolumeUnit>*        FunctionalResidualCapacity;
  QScalarQuantityWidget<VolumeUnit>*        TotalLungCapacity;
  QScalarQuantityWidget<VolumeUnit>*        TidalVolumeBaseline;
  QScalarQuantityWidget<VolumeUnit>*        ExpiratoryReserveVolume;
  QScalarQuantityWidget<VolumeUnit>*        InspiratoryCapacity;
  QScalarQuantityWidget<VolumeUnit>*        InspiratoryReserveVolume;
  QScalarQuantityWidget<VolumeUnit>*        VitalCapacity;
  QScalarQuantityWidget<VolumeUnit>*        ResidualVolume;

  QScalarQuantityWidget<FrequencyUnit>*     HeartRateBaseline;
  QScalarQuantityWidget<VolumeUnit>*        BloodVolumeBaseline;
  QScalarQuantityWidget<PressureUnit>*      SystolicArterialPressureBaseline;
  QScalarQuantityWidget<PressureUnit>*      DiastolicArterialPressureBaseline;
  QScalarQuantityWidget<PressureUnit>*      MeanArterialPressureBaseline;

  QScalarQuantityWidget<FrequencyUnit>*     HeartRateMaximum;
  QScalarQuantityWidget<FrequencyUnit>*     HeartRateMinimum;

};

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

  m_Controls->NameLayout = new QHBoxLayout();
  m_Controls->NameLayout->setSpacing(6);
  m_Controls->NameLayout->setContentsMargins(-1, 3, -1, 3);
  QSizePolicy NsizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  NsizePolicy.setHorizontalStretch(0);
  NsizePolicy.setVerticalStretch(0);
  m_Controls->NameLabel = new QLabel("Name", this);
  NsizePolicy.setHeightForWidth(m_Controls->NameLabel->sizePolicy().hasHeightForWidth());
  m_Controls->NameLabel->setSizePolicy(NsizePolicy);
  m_Controls->NameLayout->addWidget(m_Controls->NameLabel);
  m_Controls->NameSpacer = new QSpacerItem(40, 30, QSizePolicy::Expanding, QSizePolicy::Maximum);
  m_Controls->NameLayout->addItem(m_Controls->NameSpacer);
  m_Controls->NameValue = new QLineEdit(this);
  m_Controls->NameValue->setMinimumSize(QSize(148, 0));
  m_Controls->NameValue->setMaximumSize(QSize(148, 16777215));
  m_Controls->NameLayout->addWidget(m_Controls->NameValue);
  m_Controls->Name = new QWidget(this);
  m_Controls->Name->setLayout(m_Controls->NameLayout);
  m_Controls->Properties->layout()->addWidget(m_Controls->Name);

  m_Controls->SexLayout = new QHBoxLayout();
  m_Controls->SexLayout->setSpacing(6);
  m_Controls->SexLayout->setContentsMargins(-1, 3, -1, 3);
  QSizePolicy SsizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  SsizePolicy.setHorizontalStretch(0);
  SsizePolicy.setVerticalStretch(0);
  m_Controls->SexLabel = new QLabel("Sex", this);
  SsizePolicy.setHeightForWidth(m_Controls->SexLabel->sizePolicy().hasHeightForWidth());
  m_Controls->SexLabel->setSizePolicy(SsizePolicy);
  m_Controls->SexLayout->addWidget(m_Controls->SexLabel);
  m_Controls->SexSpacer = new QSpacerItem(40, 30, QSizePolicy::Expanding, QSizePolicy::Maximum);
  m_Controls->SexLayout->addItem(m_Controls->SexSpacer);
  m_Controls->SexValue = new QComboBox(this); 
  m_Controls->SexValue->addItem("Male");
  m_Controls->SexValue->addItem("Female");
  m_Controls->SexValue->setMinimumSize(QSize(70, 0));
  m_Controls->SexValue->setMaximumSize(QSize(70, 16777215));
  m_Controls->SexLayout->addWidget(m_Controls->SexValue);
  m_Controls->Sex = new QWidget(this);
  m_Controls->Sex->setLayout(m_Controls->SexLayout);
  m_Controls->Properties->layout()->addWidget(m_Controls->Sex);

  m_Controls->Age = new QScalarQuantityWidget<TimeUnit>("Age", 18, 65, 1, TimeUnit::yr, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->Age);
  m_Controls->Weight = new QScalarQuantityWidget<MassUnit>("Weight", 90, 300, 1, MassUnit::lb, ScalarOptionWidget::Check, this);
  m_Controls->Weight->addUnit(MassUnit::kg);
  m_Controls->Properties->layout()->addWidget(m_Controls->Weight);
  m_Controls->Height = new QScalarQuantityWidget<LengthUnit>("Height", 48, 96, 0.1, LengthUnit::in, ScalarOptionWidget::Check, this);
  m_Controls->Height->addUnit(LengthUnit::ft);
  m_Controls->Height->addUnit(LengthUnit::m);
  m_Controls->Properties->layout()->addWidget(m_Controls->Height);
  m_Controls->BodyDensity = new QScalarQuantityWidget<MassPerVolumeUnit>("Body Density", 0, 1000, 1, MassPerVolumeUnit::kg_Per_L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->BodyDensity);
  m_Controls->BodyFatFraction = new QScalarWidget("Body Fat Fraction", 0, 1, 0.1, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->BodyFatFraction);
  m_Controls->LeanBodyMass = new QScalarQuantityWidget<MassUnit>("Lean Body Mass", 0, 1000, 1, MassUnit::lb, ScalarOptionWidget::Check, this);
  m_Controls->LeanBodyMass->addUnit(MassUnit::kg);
  m_Controls->Properties->layout()->addWidget(m_Controls->LeanBodyMass);
  m_Controls->SkinSurfaceArea = new QScalarQuantityWidget<AreaUnit>("Skin Surface Area", 0, 4, 0.1, AreaUnit::m2, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->SkinSurfaceArea);
  m_Controls->BasalMetabolicRate = new QScalarQuantityWidget<PowerUnit>("Basal Metabolic Rate", 0, 3000, 1, PowerUnit::kcal_Per_day, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->BasalMetabolicRate);

  m_Controls->AlveoliSurfaceArea = new QScalarQuantityWidget<AreaUnit>("Alveoli Surface Area", 0, 100, 0.1, AreaUnit::m2, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->AlveoliSurfaceArea);
  m_Controls->RightLungRatio = new QScalarWidget("Right Lung Ratio", 0, 1, 0.1, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->RightLungRatio);
  m_Controls->RespirationRateBaseline = new QScalarQuantityWidget<FrequencyUnit>("Respiration Rate Baseline", 0, 30, 1, FrequencyUnit::Per_min, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->RespirationRateBaseline);
  m_Controls->FunctionalResidualCapacity = new QScalarQuantityWidget<VolumeUnit>("Functional Residual Capacity", 0, 4, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->FunctionalResidualCapacity);
  m_Controls->TotalLungCapacity = new QScalarQuantityWidget<VolumeUnit>("Total Lung Capacity", 0, 10, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->TotalLungCapacity);
  m_Controls->TidalVolumeBaseline = new QScalarQuantityWidget<VolumeUnit>("Tidal Volume Baseline", 0, 1, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->TidalVolumeBaseline);
  m_Controls->ExpiratoryReserveVolume = new QScalarQuantityWidget<VolumeUnit>("Expiratory Reserve Volume", 0, 2, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->ExpiratoryReserveVolume);
  m_Controls->InspiratoryCapacity = new QScalarQuantityWidget<VolumeUnit>("Inspiratory Capacity", 0, 8, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->InspiratoryCapacity);
  m_Controls->InspiratoryReserveVolume = new QScalarQuantityWidget<VolumeUnit>("Inspiratory Reserve Volume", 0, 8, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->InspiratoryReserveVolume);
  m_Controls->VitalCapacity = new QScalarQuantityWidget<VolumeUnit>("Vital Capacity", 0, 10, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->VitalCapacity);
  m_Controls->ResidualVolume = new QScalarQuantityWidget<VolumeUnit>("Residual Volume", 0, 3, 0.1, VolumeUnit::L, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->ResidualVolume);

  m_Controls->HeartRateBaseline = new QScalarQuantityWidget<FrequencyUnit>("Heart Rate Baseline", 0, 250, 1, FrequencyUnit::Per_min, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->HeartRateBaseline);
  m_Controls->BloodVolumeBaseline = new QScalarQuantityWidget<VolumeUnit>("Blood Volume Baseline", 0, 8000, 1, VolumeUnit::mL, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->BloodVolumeBaseline);
  m_Controls->SystolicArterialPressureBaseline = new QScalarQuantityWidget<PressureUnit>("Systolic Pressure Baseline", 0, 200, 1, PressureUnit::mmHg, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->SystolicArterialPressureBaseline);
  m_Controls->DiastolicArterialPressureBaseline = new QScalarQuantityWidget<PressureUnit>("Diastolic Pressure Baseline", 0, 120, 1, PressureUnit::mmHg, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->DiastolicArterialPressureBaseline);
  m_Controls->MeanArterialPressureBaseline = new QScalarQuantityWidget<PressureUnit>("Mean Arterial Pressure Baseline", 0, 160, 1, PressureUnit::mmHg, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->MeanArterialPressureBaseline);

  m_Controls->HeartRateMaximum = new QScalarQuantityWidget<FrequencyUnit>("Heart Rate Maximum", 0, 250, 1, FrequencyUnit::Per_min, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->HeartRateMaximum);
  m_Controls->HeartRateMinimum = new QScalarQuantityWidget<FrequencyUnit>("Heart Rate Minimum", 0, 100, 1, FrequencyUnit::Per_min, ScalarOptionWidget::Check, this);
  m_Controls->Properties->layout()->addWidget(m_Controls->HeartRateMinimum);

  QSpacerItem *spacer = new QSpacerItem(40, 1000, QSizePolicy::Expanding, QSizePolicy::Expanding);
  m_Controls->Properties->layout()->addItem(spacer);

  connect(m_Controls->ShowAdvancedProperties, SIGNAL(clicked()), this, SLOT(ShowAdvancedProperties()));
  connect(m_Controls->SaveState, SIGNAL(clicked()), this, SLOT(SetStateFilename()));
  connect(m_Controls->ResetPatient, SIGNAL(clicked()), this, SLOT(ResetPatientControls()));
  connect(m_Controls->LoadPatient,  SIGNAL(clicked()), this, SLOT(LoadPatientFile()));
  connect(m_Controls->SavePatient,  SIGNAL(clicked()), this, SLOT(SavePatientFile()));
  Reset();
  ShowAdvancedProperties();

}

QPatientEditorWidget::~QPatientEditorWidget()
{
  delete m_Controls;
}


void QPatientEditorWidget::UpdateUI()
{

}

void QPatientEditorWidget::Reset()
{
  ResetPatientControls();
  m_Controls->StateLocation = "";
  m_Controls->StateFilename->setText("");
  m_Controls->SaveState->setEnabled(true);
  m_Controls->ResetPatient->setEnabled(true);
  m_Controls->LoadPatient->setEnabled(true);
  m_Controls->SavePatient->setEnabled(true);
}

bool QPatientEditorWidget::ValidPatient()
{
  return !m_Controls->NameValue->text().isEmpty();
}

void QPatientEditorWidget::ResetPatientControls()
{
  m_Controls->SaveState->setEnabled(true);

  m_Controls->NameValue->setText("");
  m_Controls->NameValue->setEnabled(true);

  m_Controls->Age->reset();
  m_Controls->Weight->reset();
  m_Controls->Height->reset();
  m_Controls->BodyDensity->reset();
  m_Controls->BodyFatFraction->reset();
  m_Controls->LeanBodyMass->reset();
  m_Controls->SkinSurfaceArea->reset();
  m_Controls->BasalMetabolicRate->reset();

  m_Controls->AlveoliSurfaceArea->reset();
  m_Controls->RightLungRatio->reset();
  m_Controls->RespirationRateBaseline->reset();
  m_Controls->FunctionalResidualCapacity->reset();
  m_Controls->TotalLungCapacity->reset();
  m_Controls->TidalVolumeBaseline->reset();
  m_Controls->ExpiratoryReserveVolume->reset();
  m_Controls->InspiratoryCapacity->reset();
  m_Controls->InspiratoryReserveVolume->reset();
  m_Controls->VitalCapacity->reset();
  m_Controls->ResidualVolume->reset();

  m_Controls->HeartRateBaseline->reset();
  m_Controls->BloodVolumeBaseline->reset();
  m_Controls->SystolicArterialPressureBaseline->reset();
  m_Controls->DiastolicArterialPressureBaseline->reset();
  m_Controls->MeanArterialPressureBaseline->reset();

  m_Controls->HeartRateMaximum->reset();
  m_Controls->HeartRateMinimum->reset();
}

void QPatientEditorWidget::ShowAdvancedProperties()
{
  if (m_Controls->ShowAdvancedProperties->isChecked())
  {
    m_Controls->BodyDensity->show();
    m_Controls->LeanBodyMass->show();
    m_Controls->SkinSurfaceArea->show();
    m_Controls->BasalMetabolicRate->show();

    m_Controls->AlveoliSurfaceArea->show();
    m_Controls->RightLungRatio->show();

    m_Controls->BloodVolumeBaseline->show();
    m_Controls->MeanArterialPressureBaseline->show();

    m_Controls->FunctionalResidualCapacity->show();
    m_Controls->TotalLungCapacity->show();
    m_Controls->TidalVolumeBaseline->show();
    m_Controls->ExpiratoryReserveVolume->show();
    m_Controls->InspiratoryCapacity->show();
    m_Controls->InspiratoryReserveVolume->show();
    m_Controls->VitalCapacity->show();
    m_Controls->ResidualVolume->show();

    m_Controls->HeartRateMaximum->show();
    m_Controls->HeartRateMinimum->show();
  }
  else
  {
    m_Controls->BodyDensity->hide();
    m_Controls->LeanBodyMass->hide();
    m_Controls->SkinSurfaceArea->hide();
    m_Controls->BasalMetabolicRate->hide();

    m_Controls->AlveoliSurfaceArea->hide();
    m_Controls->RightLungRatio->hide();

    m_Controls->BloodVolumeBaseline->hide();
    m_Controls->MeanArterialPressureBaseline->hide();

    m_Controls->FunctionalResidualCapacity->hide();
    m_Controls->TotalLungCapacity->hide();
    m_Controls->TidalVolumeBaseline->hide();
    m_Controls->ExpiratoryReserveVolume->hide();
    m_Controls->InspiratoryCapacity->hide();
    m_Controls->InspiratoryReserveVolume->hide();
    m_Controls->VitalCapacity->hide();
    m_Controls->ResidualVolume->hide();

    m_Controls->HeartRateMaximum->hide();
    m_Controls->HeartRateMinimum->hide();
  }
}

void QPatientEditorWidget::SetStateFilename()
{
  QString fileName = QFileDialog::getSaveFileName(this, "Save state file", "./states", "State Files (*.json)");
  if (fileName.isEmpty())
    return;

  m_Controls->StateLocation = fileName.toStdString();

  QStringList pieces = fileName.split("/");
  m_Controls->StateFilename->setText("New state filename : "+ pieces.value(pieces.length() - 1));
}

void QPatientEditorWidget::EnableInput(bool b)
{
  EnableConverter(!b);

  m_Controls->NameLabel->setEnabled(b);
  m_Controls->NameValue->setEnabled(b);
  m_Controls->SexLabel->setEnabled(b);
  m_Controls->SexValue->setEnabled(b);

  m_Controls->Age->enableInput(b);
  m_Controls->Weight->enableInput(b);
  m_Controls->Height->enableInput(b);
  m_Controls->BodyDensity->enableInput(b);
  m_Controls->BodyFatFraction->enableInput(b);
  m_Controls->LeanBodyMass->enableInput(b);
  m_Controls->SkinSurfaceArea->enableInput(b);
  m_Controls->BasalMetabolicRate->enableInput(b);

  m_Controls->AlveoliSurfaceArea->enableInput(b);
  m_Controls->RightLungRatio->enableInput(b);
  m_Controls->RespirationRateBaseline->enableInput(b);
  m_Controls->FunctionalResidualCapacity->enableInput(b);
  m_Controls->TotalLungCapacity->enableInput(b);
  m_Controls->TidalVolumeBaseline->enableInput(b);
  m_Controls->ExpiratoryReserveVolume->enableInput(b);
  m_Controls->InspiratoryCapacity->enableInput(b);
  m_Controls->InspiratoryReserveVolume->enableInput(b);
  m_Controls->VitalCapacity->enableInput(b);
  m_Controls->ResidualVolume->enableInput(b);

  m_Controls->HeartRateBaseline->enableInput(b);
  m_Controls->BloodVolumeBaseline->enableInput(b);
  m_Controls->SystolicArterialPressureBaseline->enableInput(b);
  m_Controls->DiastolicArterialPressureBaseline->enableInput(b);
  m_Controls->MeanArterialPressureBaseline->enableInput(b);

  m_Controls->HeartRateMaximum->enableInput(b);
  m_Controls->HeartRateMinimum->enableInput(b);

  m_Controls->ResetPatient->setEnabled(b);
  m_Controls->LoadPatient->setEnabled(b);
  m_Controls->SavePatient->setEnabled(b);

  m_Controls->SaveState->setEnabled(b);
}

void QPatientEditorWidget::EnableConverter(bool b)
{
  m_Controls->Age->enableConverter(b);
  m_Controls->Weight->enableConverter(b);
  m_Controls->Height->enableConverter(b);
  m_Controls->BodyDensity->enableConverter(b);
  m_Controls->LeanBodyMass->enableConverter(b);
  m_Controls->SkinSurfaceArea->enableConverter(b);
  m_Controls->BasalMetabolicRate->enableConverter(b);

  m_Controls->AlveoliSurfaceArea->enableConverter(b);
  m_Controls->RespirationRateBaseline->enableConverter(b);
  m_Controls->FunctionalResidualCapacity->enableConverter(b);
  m_Controls->TotalLungCapacity->enableConverter(b);
  m_Controls->TidalVolumeBaseline->enableConverter(b);
  m_Controls->ExpiratoryReserveVolume->enableConverter(b);
  m_Controls->InspiratoryCapacity->enableConverter(b);
  m_Controls->InspiratoryReserveVolume->enableConverter(b);
  m_Controls->VitalCapacity->enableConverter(b);
  m_Controls->ResidualVolume->enableConverter(b);

  m_Controls->HeartRateBaseline->enableConverter(b);
  m_Controls->BloodVolumeBaseline->enableConverter(b);
  m_Controls->SystolicArterialPressureBaseline->enableConverter(b);
  m_Controls->DiastolicArterialPressureBaseline->enableConverter(b);
  m_Controls->MeanArterialPressureBaseline->enableConverter(b);

  m_Controls->HeartRateMaximum->enableConverter(b);
  m_Controls->HeartRateMinimum->enableConverter(b);
}

void QPatientEditorWidget::LoadPatientFile()
{
  QString fileName = QFileDialog::getOpenFileName(this,
    "Open Patient", "./patients", "Patient Files (*.json)");
  if (fileName.isEmpty())
    return;

  std::string s = fileName.toStdString();
  if (!m_Controls->Pulse.GetPatientConfiguration().GetPatient().SerializeFromFile(s, SerializationFormat::JSON))
  {
    QMessageBox msgBox(this);
    msgBox.setWindowTitle("Error!");
    QString err = "Unable to load patient file : " + fileName;
    msgBox.setText(err);
    msgBox.exec();
    return;
  }
  PatientToControls();
}


void QPatientEditorWidget::SavePatientFile()
{
  QString fileName = QFileDialog::getSaveFileName(this, "Save file", "./patients", "Patient Files (*.json)");
  if (fileName.isEmpty())
    return;

  if (m_Controls->NameValue->text().isEmpty())
  {
    QMessageBox msgBox(this);
    msgBox.setWindowTitle("Error!");
    msgBox.setText("Patient must have a name");
    msgBox.exec();
    return;
  }
  m_Controls->Pulse.GetPatientConfiguration().GetPatient().SerializeToFile(fileName.toStdString(), SerializationFormat::JSON);
}

void QPatientEditorWidget::PatientToControls()
{
  ResetPatientControls();
  SEPatient& Patient = m_Controls->Pulse.GetPatientConfiguration().GetPatient();

  if (Patient.HasName())
    m_Controls->NameValue->setText(QString::fromStdString(Patient.GetName()));
   m_Controls->SexValue->setCurrentIndex(Patient.GetSex() == ePatient_Sex::Male ? 0 : 1);
   if (Patient.HasAge())
   {
     m_Controls->Age->enableInput(true);
     m_Controls->Age->setValue(Patient.GetAge());
   }
  if (Patient.HasWeight())
  {
    m_Controls->Weight->enableInput(true);
    m_Controls->Weight->setValue(Patient.GetWeight());
  }
  if (Patient.HasHeight())
  {
    m_Controls->Height->enableInput(true);
    m_Controls->Height->setValue(Patient.GetHeight());
  }
  if (Patient.HasBodyDensity())
  {
    m_Controls->BodyDensity->enableInput(true);
    m_Controls->BodyDensity->setValue(Patient.GetBodyDensity());
  }
  if (Patient.HasBodyFatFraction())
  {
    m_Controls->BodyFatFraction->enableInput(true);
    m_Controls->BodyFatFraction->setValue(Patient.GetBodyFatFraction());
  }
  if (Patient.HasLeanBodyMass())
  {
    m_Controls->LeanBodyMass->enableInput(true);
    m_Controls->LeanBodyMass->setValue(Patient.GetLeanBodyMass());
  }
  if (Patient.HasSkinSurfaceArea())
  {
    m_Controls->SkinSurfaceArea->enableInput(true);
    m_Controls->SkinSurfaceArea->setValue(Patient.GetSkinSurfaceArea());
  }
  if (Patient.HasBasalMetabolicRate())
  {
    m_Controls->BasalMetabolicRate->enableInput(true);
    m_Controls->BasalMetabolicRate->setValue(Patient.GetBasalMetabolicRate());
  }

  if (Patient.HasAlveoliSurfaceArea())
  {
    m_Controls->AlveoliSurfaceArea->enableInput(true);
    m_Controls->AlveoliSurfaceArea->setValue(Patient.GetAlveoliSurfaceArea());
  }
  if (Patient.HasRightLungRatio())
  {
    m_Controls->RightLungRatio->enableInput(true);
    m_Controls->RightLungRatio->setValue(Patient.GetRightLungRatio());
  }
  if (Patient.HasRespirationRateBaseline())
  {
    m_Controls->RespirationRateBaseline->enableInput(true);
    m_Controls->RespirationRateBaseline->setValue(Patient.GetRespirationRateBaseline());
  }
  if (Patient.HasFunctionalResidualCapacity())
  {
    m_Controls->FunctionalResidualCapacity->enableInput(true);
    m_Controls->FunctionalResidualCapacity->setValue(Patient.GetFunctionalResidualCapacity());
  }
  if (Patient.HasTotalLungCapacity())
  {
    m_Controls->TotalLungCapacity->enableInput(true);
    m_Controls->TotalLungCapacity->setValue(Patient.GetTotalLungCapacity());
  }
  if (Patient.HasTidalVolumeBaseline())
  {
    m_Controls->TidalVolumeBaseline->enableInput(true);
    m_Controls->TidalVolumeBaseline->setValue(Patient.GetTidalVolumeBaseline());
  }
  if (Patient.HasExpiratoryReserveVolume())
  {
    m_Controls->ExpiratoryReserveVolume->enableInput(true);
    m_Controls->ExpiratoryReserveVolume->setValue(Patient.GetExpiratoryReserveVolume());
  }
  if (Patient.HasInspiratoryCapacity())
  {
    m_Controls->InspiratoryCapacity->enableInput(true);
    m_Controls->InspiratoryCapacity->setValue(Patient.GetInspiratoryCapacity());
  }
  if (Patient.HasInspiratoryReserveVolume())
  {
    m_Controls->InspiratoryReserveVolume->enableInput(true);
    m_Controls->InspiratoryReserveVolume->setValue(Patient.GetInspiratoryReserveVolume());
  }
  if (Patient.HasVitalCapacity())
  {
    m_Controls->VitalCapacity->enableInput(true);
    m_Controls->VitalCapacity->setValue(Patient.GetVitalCapacity());
  }
  if (Patient.HasResidualVolume())
  {
    m_Controls->ResidualVolume->enableInput(true);
    m_Controls->ResidualVolume->setValue(Patient.GetResidualVolume());
  }

  if (Patient.HasBloodVolumeBaseline())
  {
    m_Controls->BloodVolumeBaseline->enableInput(true);
    m_Controls->BloodVolumeBaseline->setValue(Patient.GetBloodVolumeBaseline());
  }
  if (Patient.HasDiastolicArterialPressureBaseline())
  {
    m_Controls->DiastolicArterialPressureBaseline->enableInput(true);
    m_Controls->DiastolicArterialPressureBaseline->setValue(Patient.GetDiastolicArterialPressureBaseline());
  }
  if (Patient.HasSystolicArterialPressureBaseline())
  {
    m_Controls->SystolicArterialPressureBaseline->enableInput(true);
    m_Controls->SystolicArterialPressureBaseline->setValue(Patient.GetSystolicArterialPressureBaseline());
  }
  if (Patient.HasHeartRateBaseline())
  {
    m_Controls->HeartRateBaseline->enableInput(true);
    m_Controls->HeartRateBaseline->setValue(Patient.GetHeartRateBaseline());
  }
  if (Patient.HasMeanArterialPressureBaseline())
  {
    m_Controls->MeanArterialPressureBaseline->enableInput(true);
    m_Controls->MeanArterialPressureBaseline->setValue(Patient.GetMeanArterialPressureBaseline());
  }

  if (Patient.HasHeartRateMaximum())
  {
    m_Controls->HeartRateMaximum->enableInput(true);
    m_Controls->HeartRateMaximum->setValue(Patient.GetHeartRateMaximum());
  }
  if (Patient.HasHeartRateMinimum())
  {
    m_Controls->HeartRateMinimum->enableInput(true);
    m_Controls->HeartRateMinimum->setValue(Patient.GetHeartRateMinimum());
  }
}

void QPatientEditorWidget::ControlsToPatient()
{
  SEPatient& Patient = m_Controls->Pulse.GetPatientConfiguration().GetPatient();
  Patient.Clear();
  Patient.SetName(m_Controls->NameValue->text().toStdString());
  Patient.SetSex(m_Controls->SexValue->currentIndex() == 0 ? ePatient_Sex::Male : ePatient_Sex::Female);
  if (m_Controls->Age->isChecked())
    m_Controls->Age->getValue(Patient.GetAge());
  if (m_Controls->Weight->isChecked())
    m_Controls->Weight->getValue(Patient.GetWeight());
  if (m_Controls->Height->isChecked())
    m_Controls->Height->getValue(Patient.GetHeight());
  if (m_Controls->BodyDensity->isChecked())
    m_Controls->BodyDensity->getValue(Patient.GetBodyDensity());
  if (m_Controls->BodyFatFraction->isChecked())
    m_Controls->BodyFatFraction->getValue(Patient.GetBodyFatFraction());
  if (m_Controls->LeanBodyMass->isChecked())
    m_Controls->LeanBodyMass->getValue(Patient.GetLeanBodyMass());
  if (m_Controls->SkinSurfaceArea->isChecked())
    m_Controls->SkinSurfaceArea->getValue(Patient.GetSkinSurfaceArea());
  if (m_Controls->BasalMetabolicRate->isChecked())
    m_Controls->BasalMetabolicRate->getValue(Patient.GetBasalMetabolicRate());

  if (m_Controls->AlveoliSurfaceArea->isChecked())
    m_Controls->AlveoliSurfaceArea->getValue(Patient.GetAlveoliSurfaceArea());
  if (m_Controls->RightLungRatio->isChecked())
    m_Controls->RightLungRatio->getValue(Patient.GetRightLungRatio());
  if (m_Controls->RespirationRateBaseline->isChecked())
    m_Controls->RespirationRateBaseline->getValue(Patient.GetRespirationRateBaseline());
  if (m_Controls->FunctionalResidualCapacity->isChecked())
    m_Controls->FunctionalResidualCapacity->getValue(Patient.GetFunctionalResidualCapacity());
  if (m_Controls->TotalLungCapacity->isChecked())
    m_Controls->TotalLungCapacity->getValue(Patient.GetTotalLungCapacity());
  if (m_Controls->TidalVolumeBaseline->isChecked())
    m_Controls->TidalVolumeBaseline->getValue(Patient.GetTidalVolumeBaseline());
  if (m_Controls->ExpiratoryReserveVolume->isChecked())
    m_Controls->ExpiratoryReserveVolume->getValue(Patient.GetExpiratoryReserveVolume());
  if (m_Controls->InspiratoryCapacity->isChecked())
    m_Controls->InspiratoryCapacity->getValue(Patient.GetInspiratoryCapacity());
  if (m_Controls->InspiratoryReserveVolume->isChecked())
    m_Controls->InspiratoryReserveVolume->getValue(Patient.GetInspiratoryReserveVolume());
  if (m_Controls->VitalCapacity->isChecked())
    m_Controls->VitalCapacity->getValue(Patient.GetVitalCapacity());
  if (m_Controls->ResidualVolume->isChecked())
    m_Controls->ResidualVolume->getValue(Patient.GetResidualVolume());

  if (m_Controls->BloodVolumeBaseline->isChecked())
    m_Controls->BloodVolumeBaseline->getValue(Patient.GetBloodVolumeBaseline());
  if (m_Controls->DiastolicArterialPressureBaseline->isChecked())
    m_Controls->DiastolicArterialPressureBaseline->getValue(Patient.GetDiastolicArterialPressureBaseline());
  if (m_Controls->SystolicArterialPressureBaseline->isChecked())
    m_Controls->SystolicArterialPressureBaseline->getValue(Patient.GetSystolicArterialPressureBaseline());
  if (m_Controls->HeartRateBaseline->isChecked())
    m_Controls->HeartRateBaseline->getValue(Patient.GetHeartRateBaseline());
  if (m_Controls->MeanArterialPressureBaseline->isChecked())
    m_Controls->MeanArterialPressureBaseline->getValue(Patient.GetMeanArterialPressureBaseline());

  if (m_Controls->HeartRateMaximum->isChecked())
    m_Controls->HeartRateMaximum->getValue(Patient.GetHeartRateMaximum());
  if (m_Controls->HeartRateMinimum->isChecked())
    m_Controls->HeartRateMinimum->getValue(Patient.GetHeartRateMinimum());
}

void QPatientEditorWidget::AtSteadyState(PhysiologyEngine& pulse)
{
  if (m_Controls->SaveState->isChecked())
    pulse.SerializeToFile(m_Controls->StateLocation, SerializationFormat::JSON);
  // Sync the GUI Patient object with what Pulse Calculated
  m_Controls->Pulse.GetPatientConfiguration().GetPatient().Copy(pulse.GetPatient());
}
void QPatientEditorWidget::AtSteadyStateUpdateUI()
{
  PatientToControls();
  EnableInput(false);
  EnableConverter(true);
}
