#include "input_physics.hpp"

QtInputPhysics::QtInputPhysics():QWidget(){
  g_label=new QLabel("Gravity (g) : ");
  rho_label=new QLabel("Fluid density (&rho;) : ");
  phi_label=new QLabel("Porosity of the soil (&phi;) : ");
  k0_label=new QLabel("Conductivity of the saturated soil (k<sub>0</sub>) : ");
  nivrivsat_label=new QLabel("Water pressure at the bottom of overland water (nivrivsat) : ");
  g_input=new QLineEdit();
  rho_input=new QLineEdit();
  phi_input=new QLineEdit();
  k0_input=new QLineEdit();
  nivrivsat_input=new QLineEdit();
  for(size_t i=0;i<max_model_parameters;++i){
    model_label[i]=new QLabel(this);
    model_input[i]=new QLineEdit(this);
  }

  //Text format
  rho_label->setTextFormat(Qt::RichText);
  phi_label->setTextFormat(Qt::RichText);
  k0_label->setTextFormat(Qt::RichText);
  for(size_t i=0;i<max_model_parameters;++i){
    model_label[i]->setTextFormat(Qt::RichText);
  }

  //Hide model parameters
  for(size_t i=0;i<max_model_parameters;++i){
    model_label[i]->hide();
    model_input[i]->hide();
  }
  //Input validators
  double_validator=new QDoubleValidator;
  positive_double_validator=new QDoubleValidator;
  positive_double_validator->setBottom(0);

 
  g_input->setValidator(positive_double_validator);
  rho_input->setValidator(double_validator);
  phi_input->setValidator(double_validator);
  k0_input->setValidator(double_validator);
  nivrivsat_input->setValidator(double_validator);

  //Boxes
  phy_common_box=new QGroupBox("Common parameters");
  phy_model_box=new QGroupBox("Model parameters");
  phy_model_selection_box=new QComboBox;
  phy_model_selection_box->addItem("Brooks and Corey");

  
  //Layouts
  base_layout=new QHBoxLayout;
  phy_common_layout=new QVBoxLayout;
  phy_model_layout=new QVBoxLayout;
  
  //Phy commont layout
  int vspace=20;
  phy_common_layout->addWidget(g_label);
  phy_common_layout->addWidget(g_input);
  phy_common_layout->addSpacing(vspace);
  phy_common_layout->addWidget(rho_label);
  phy_common_layout->addWidget(rho_input);
  phy_common_layout->addSpacing(vspace);
  phy_common_layout->addWidget(phi_label);
  phy_common_layout->addWidget(phi_input);
  phy_common_layout->addSpacing(vspace);
  phy_common_layout->addWidget(k0_label);
  phy_common_layout->addWidget(k0_input);
  phy_common_layout->addSpacing(vspace);
  phy_common_layout->addWidget(nivrivsat_label);
  phy_common_layout->addWidget(nivrivsat_input);
  phy_common_layout->addStretch();

  //Phy model layout
  phy_model_layout->addWidget(phy_model_selection_box);
  for(size_t i=0;i<max_model_parameters;++i){
    phy_model_layout->addSpacing(vspace);
    phy_model_layout->addWidget(model_label[i]);
    phy_model_layout->addWidget(model_input[i]);
  }
  phy_model_layout->addStretch();
  
  //Boxes
  phy_common_box->setLayout(phy_common_layout);
  phy_model_box->setLayout(phy_model_layout);

  //Base widget
  base_layout->addWidget(phy_common_box);
  base_layout->addWidget(phy_model_box);
  setLayout(base_layout);

  //Conections
  connect(phy_model_selection_box,QOverload<int>::of(&QComboBox::activated),this,&QtInputPhysics::modelChoosed);

  //Display model specific interface
  nb_model_parameters=0;
  modelChoosed(phy_model_selection_box->currentIndex());

  loadData();
}

QtInputPhysics::~QtInputPhysics(){

}

void
QtInputPhysics::modelChoosed(int index){
  for(size_t i=0;i<nb_model_parameters;++i){
    model_label[i]->hide();
    model_input[i]->hide();
  }
  switch(index){
  case 0:
    //Brooks and Corey
    Physics::setModel(Physics::BrooksCorey);
    nb_model_parameters=4;
    model_label[0]->setText("Minimal pressure p<sub>sat</sub> such that s(p<sub>sat</sub>)=1");
    model_input[0]->setValidator(double_validator);
    model_input[0]->setText(QString::number(Physics::model_data[0]));
    model_label[1]->setText("Minimal residual pressure (s<sub>res</sub>)");
    model_input[1]->setValidator(double_validator);
    model_input[1]->setText(QString::number(Physics::model_data[1]));
    model_label[2]->setText("&lambda; exponent");
    model_input[2]->setValidator(double_validator);
    model_input[2]->setText(QString::number(Physics::model_data[2]));
    model_label[3]->setText("&alpha; exponent");
    model_input[3]->setValidator(double_validator);
    model_input[3]->setText(QString::number(Physics::model_data[3]));
    break;
  default:
    break;
  };
  for(size_t i=0;i<nb_model_parameters;++i){
    model_label[i]->show();
    model_input[i]->show();
  }
}

QWidget*
QtInputPhysics::validate(){
  if(not g_input->hasAcceptableInput()) return g_input;
  if(not rho_input->hasAcceptableInput()) return rho_input;
  if(not phi_input->hasAcceptableInput()) return phi_input;
  if(not k0_input->hasAcceptableInput()) return k0_input;
  if(not nivrivsat_input->hasAcceptableInput()) return nivrivsat_input;
  for(size_t i=0;i<nb_model_parameters;++i){
    if(not model_input[i]->hasAcceptableInput()) return model_input[i];
  }
  return nullptr;
}

void
QtInputPhysics::save(fstream& file){
  double d;
  size_t s;
  d=g_input->text().toDouble();
  file.write((char*)&d,sizeof(double));
  d=rho_input->text().toDouble();
  file.write((char*)&d,sizeof(double));
  d=phi_input->text().toDouble();
  file.write((char*)&d,sizeof(double));
  d=k0_input->text().toDouble();
  file.write((char*)&d,sizeof(double));
  d=nivrivsat_input->text().toDouble();
  file.write((char*)&d,sizeof(double));
  s=phy_model_selection_box->currentIndex();
  file.write((char*)&s,sizeof(size_t));
  s=nb_model_parameters;
  file.write((char*)&s,sizeof(size_t));
  for(size_t i=0;i<nb_model_parameters;++i){
    d=model_input[i]->text().toDouble();
    file.write((char*)&d,sizeof(double));
  }
}

void
QtInputPhysics::load(fstream& file){
  double d;
  size_t s;
  file.read((char*)&d,sizeof(double));
  g_input->setText(QString::number(d));
  file.read((char*)&d,sizeof(double));
  rho_input->setText(QString::number(d));
  file.read((char*)&d,sizeof(double));
  phi_input->setText(QString::number(d));
  file.read((char*)&d,sizeof(double));
  k0_input->setText(QString::number(d));
  file.read((char*)&d,sizeof(double));
  nivrivsat_input->setText(QString::number(d));
  file.read((char*)&s,sizeof(size_t));
  phy_model_selection_box->setCurrentIndex(s);
  file.read((char*)&s,sizeof(size_t));
  for(size_t i=0;i<s;++i){
    file.read((char*)&d,sizeof(double));
    model_input[i]->setText(QString::number(d));
  }
}

void
QtInputPhysics::loadData(){
  g_input->setText(QString::number(Physics::g));
  rho_input->setText(QString::number(Physics::rho));
  phi_input->setText(QString::number(Physics::phi));
  k0_input->setText(QString::number(Physics::k0));
  nivrivsat_input->setText(QString::number(Physics::nivrivsat));
}
