/* Distributed under the Apache License, Version 2.0.
See accompanying NOTICE file for details.*/
#include "actions/HemorrhageWidget.h"
#include "controls/ScalarQuantityWidget.h"
#include "controls/LabeledComboBox.h"

#include "cdm/CommonDataModel.h"
#include "PhysiologyEngine.h"
#include "cdm/patient/actions/SEHemorrhage.h"
#include "cdm/properties/SEScalarVolumePerTime.h"


class QHemorrhageWidget::Controls // based off of chronic anemia widget
{
public:
  Controls() {}
  std::map<std::string,SEHemorrhage*>       Actions;
  std::vector<SEHemorrhage*>                ReadyActions;

  QLabeledComboBox*                         Type;
  QScalarQuantityWidget<VolumePerTimeUnit>* Rate;
  QLabeledComboBox*                         ExternalCmpts;
  QLabeledComboBox*                         InternalCmpts;
};

QHemorrhageWidget::QHemorrhageWidget(QPulse& qp, QWidget *parent, Qt::WindowFlags flags) : QActionWidget(qp, parent, flags)
{
  m_Controls = new Controls();
  
  std::vector<QString> typeOptions = {"External", "Internal"};
  m_Controls->Type = new QLabeledComboBox(this, "Type", typeOptions);
  Properties()->layout()->addWidget(m_Controls->Type);

  m_Controls->Rate = new QScalarQuantityWidget<VolumePerTimeUnit>("Rate", 0, 1000, 1, VolumePerTimeUnit::mL_Per_min, ScalarOptionWidget::None, this);
  m_Controls->Rate->addUnit(VolumePerTimeUnit::mL_Per_min);
  m_Controls->Rate->addUnit(VolumePerTimeUnit::L_Per_s);
  m_Controls->Rate->addUnit(VolumePerTimeUnit::L_Per_min);
  Properties()->layout()->addWidget(m_Controls->Rate);

  std::vector<QString> externalCmpts = { "RightLeg", "LeftLeg", "RightLeg", "LeftArm", "Aorta", "VenaCava" };
  m_Controls->ExternalCmpts = new QLabeledComboBox(this, "Compartments", externalCmpts, 120);
  Properties()->layout()->addWidget(m_Controls->ExternalCmpts);
  m_Controls->ExternalCmpts->show();

  std::vector<QString> internalCmpts = { "LeftKidney", "RightKidney", "Liver", "Spleen", "Splanchnic", "SmallIntestine", "LargeIntestine", "Aorta", "VenaCava" };
  m_Controls->InternalCmpts = new QLabeledComboBox(this, "Compartments", internalCmpts, 120);
  Properties()->layout()->addWidget(m_Controls->InternalCmpts);
  m_Controls->InternalCmpts->hide();

  connect(m_Controls->Type->GetComboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeType()));
  Reset();
}

QHemorrhageWidget::~QHemorrhageWidget()
{
  for (auto itr : m_Controls->Actions)
    delete itr.second;
  delete m_Controls;
}

void QHemorrhageWidget::Reset()
{
  QActionWidget::Reset();
  for (auto itr : m_Controls->Actions)
    itr.second->Clear();
}

void QHemorrhageWidget::SetEnabled(bool b)
{
  QActionWidget::SetEnabled(b);
  m_Controls->Type->SetEnabled(b);
  m_Controls->Rate->enableInput(b);;
  m_Controls->Rate->setEnabled(b);
  if (!b)
  {
    m_Controls->ExternalCmpts->SetEnabled(b);
    m_Controls->InternalCmpts->SetEnabled(b);
  }
  else
    ChangeType();
}

void QHemorrhageWidget::ChangeType()
{
  if (m_Controls->Type->GetText() == "External")
  {
    m_Controls->ExternalCmpts->show();
    m_Controls->ExternalCmpts->SetEnabled(true);
    m_Controls->InternalCmpts->hide();
    m_Controls->InternalCmpts->SetEnabled(false);
  }
  else
  {
    m_Controls->ExternalCmpts->hide();
    m_Controls->ExternalCmpts->SetEnabled(false);
    m_Controls->InternalCmpts->show();
    m_Controls->InternalCmpts->SetEnabled(true);
  }
}

void QHemorrhageWidget::ControlsToAction()
{
  QActionWidget::ControlsToAction();

  std::string cmpt;
  SEHemorrhage* h = nullptr;
  if (m_Controls->Type->GetText() == "External")
  {
    cmpt = m_Controls->ExternalCmpts->GetText();
    if (m_Controls->Actions.find(cmpt) == m_Controls->Actions.end())
      m_Controls->Actions[cmpt] = new SEHemorrhage();
    h = m_Controls->Actions[cmpt];
    h->SetType(eHemorrhage_Type::External);
  }
  else
  {
    cmpt = m_Controls->InternalCmpts->GetText();
    if (m_Controls->Actions.find(cmpt) == m_Controls->Actions.end())
      m_Controls->Actions[cmpt] = new SEHemorrhage();
    h = m_Controls->Actions[cmpt];
    h->SetType(eHemorrhage_Type::Internal);
  }
  h->SetCompartment(cmpt);
  m_Controls->Rate->getValue(h->GetRate());
  m_Controls->ReadyActions.push_back(h);
}

void QHemorrhageWidget::AtSteadyState(PhysiologyEngine& pulse)
{
  // Nothing expected here
}
void QHemorrhageWidget::AtSteadyStateUpdateUI()
{
  // Nothing expected here
}

void QHemorrhageWidget::ProcessPhysiology(PhysiologyEngine& pulse)
{// This is called from a thread, you should NOT update UI here
  // This is where we pull data from pulse, and push any actions to it
  for (auto h : m_Controls->ReadyActions)
  {
    if (h->IsValid())
      pulse.ProcessAction(*h);
  }
  m_Controls->ReadyActions.clear();
}
void QHemorrhageWidget::PhysiologyUpdateUI()
{// This is called from a slot, you can update UI here

  // Nothing is expected to be in the environment
}