//********************************************************************************
//*
//*  C++ finite element method for heat equation
//*  James sandham
//*  15 April 2015
//*
//********************************************************************************

//********************************************************************************
//
// HeatFE is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//
//********************************************************************************

#include <QtGui>

#include<iostream>
#include "RunWizard.h"
#include "Mesh.h"
#include "FeModel.h"
#include "BoundaryData.h"
#include "Solver.h"


//----------------------------------------------------------------------------
// constructor for run wizard
//----------------------------------------------------------------------------
RunWizard::RunWizard(Mesh *msh, QWidget *parent)
     : QWizard(parent)
{
     mesh = msh;
     bdata = new BoundaryData(mesh->Ng);

     for(int i=0;i<mesh->Ng;i++){bdata->groups[i] = mesh->groups[i];}

     addPage(new IntroPage);
     addPage(new TimePage);
     addPage(new MaterialPage);
     addPage(new BoundaryPage(bdata));
     addPage(new LaunchPage);

     setPixmap(QWizard::BannerPixmap, QPixmap(":/beam.jpg"));//":/images/banner.png"));
     setPixmap(QWizard::BackgroundPixmap, QPixmap(":/beam.jpg"));//":/images/background.png"));

     setWindowTitle(tr("Class Wizard"));
}


//----------------------------------------------------------------------------
// destructor for run wizard
//----------------------------------------------------------------------------
RunWizard::~RunWizard()
{
  delete fem;
  delete bdata;
}


void RunWizard::accept()
{
  //launch model (call finite element solver)
  fem = new FeModel(bdata);

  if(field("stationary").toBool()){fem->set_time(false);}
  if(field("transient").toBool()){fem->set_time(true);}
  fem->set_dt(field("dt").toDouble());
  fem->set_steps(field("steps").toInt());
  fem->set_rho(field("rho").toDouble());
  fem->set_c(field("c").toDouble());
  fem->set_Q(field("Q").toDouble());
  fem->set_k(field("k").toDouble());

  SolverHeat solver(*mesh,*fem);  //create solver object and pass model to constructor

  int itr = solver.solve();     //solve Global system

  std::cout<<"iterations: "<<itr<<std::endl;
  
  for(int i=0;i<fem->bdata->numOfGrps;i++){
    std::cout<<"boundary type: "<<fem->bdata->types[i]<<std::endl;
    std::cout<<"boundary values: "<<fem->bdata->values[i]<<std::endl;
  }

  close();
}


//----------------------------------------------------------------------------
// constructor for intro page
//----------------------------------------------------------------------------
IntroPage::IntroPage(QWidget *parent)
     : QWizardPage(parent)
{
     setTitle(tr("Introduction"));
     setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png"));

     label = new QLabel(tr("This wizard is used to setup the model by asking "
                           "user input on multi-physics setup, time parameters, "
                           "material properties, and boundary conditions"));
     label->setWordWrap(true);

     layout = new QVBoxLayout;
     layout->addWidget(label);
     setLayout(layout);
}


//----------------------------------------------------------------------------
// destructor for intro page
//----------------------------------------------------------------------------
IntroPage::~IntroPage()
{
  delete layout;
  delete label;
}


//----------------------------------------------------------------------------
// constructor for time
//----------------------------------------------------------------------------
TimePage::TimePage(QWidget *parent)
     : QWizardPage(parent)
{
     setTitle(tr("Time Information"));
     setSubTitle(tr("Specify whether model is stationary or transient"));
     setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));

     layout = new QVBoxLayout;

     layout_top = new QHBoxLayout;
     stationaryRadioButton = new QRadioButton(tr("stationary"));
     transientRadioButton = new QRadioButton(tr("transient"));
     stationaryRadioButton->setChecked(true);
   
     layout_top->addWidget(stationaryRadioButton);
     layout_top->addWidget(transientRadioButton);
     layout->addLayout(layout_top);

     layout_bot = new QHBoxLayout;
     layout_bot_left = new QVBoxLayout;
     layout_bot_right = new QVBoxLayout;     
     layout1 = new QHBoxLayout;
     layout2 = new QHBoxLayout;
     dtLabel = new QLabel(tr("dt")); dtLineEdit = new QLineEdit(); dtLineEdit->setEnabled(false);
     ntLabel = new QLabel(tr("steps")); ntLineEdit = new QLineEdit(); ntLineEdit->setEnabled(false);
     layout1->addWidget(dtLabel); layout1->addWidget(dtLineEdit);
     layout2->addWidget(ntLabel); layout2->addWidget(ntLineEdit);
     layout_bot_right->addLayout(layout1);
     layout_bot_right->addLayout(layout2);
     layout_bot->addLayout(layout_bot_left);
     layout_bot->addLayout(layout_bot_right);
     layout->addLayout(layout_bot);

     connect(stationaryRadioButton, SIGNAL(clicked()), this, SLOT(stationary()));
     connect(transientRadioButton, SIGNAL(clicked()), this, SLOT(transient()));
     connect(stationaryRadioButton, SIGNAL(clicked()), dtLineEdit, SLOT(clear()));
     connect(stationaryRadioButton, SIGNAL(clicked()), ntLineEdit, SLOT(clear()));
     connect(dtLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(completeChanged()));
     connect(ntLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(completeChanged()));
     connect(stationaryRadioButton, SIGNAL(clicked()), this, SIGNAL(completeChanged()));
     connect(transientRadioButton, SIGNAL(clicked()), this, SIGNAL(completeChanged()));

     registerField("stationary",stationaryRadioButton);
     registerField("transient",transientRadioButton);
     registerField("dt", dtLineEdit);
     registerField("steps", ntLineEdit);

     setLayout(layout);
}


//----------------------------------------------------------------------------
// destructor for time page
//---------------------------------------------------------------------------
TimePage::~TimePage()
{
     delete layout;
     delete layout_top;
     delete layout_bot;
     delete layout_bot_left;
     delete layout_bot_right;
     delete layout1;
     delete layout2;

     delete stationaryRadioButton;
     delete transientRadioButton;
     delete dtLabel; 
     delete dtLineEdit;
     delete ntLabel; 
     delete ntLineEdit;
}


bool TimePage::isComplete()const
{
  if(stationaryRadioButton->isChecked()){
    dtLineEdit->setModified(false);
    ntLineEdit->setModified(false);
    return true;
  }
  else if(transientRadioButton->isChecked()){
    if(dtLineEdit->isModified() && ntLineEdit->isModified()){
      return true;
    }  
  }
  else{
    return false;
  }
}


void TimePage::stationary()
{
    dtLineEdit->setEnabled(false);
    ntLineEdit->setEnabled(false);
}


void TimePage::transient()
{
    dtLineEdit->setEnabled(true);
    ntLineEdit->setEnabled(true);
}


//----------------------------------------------------------------------------
// constructor Multi-phsics page
//----------------------------------------------------------------------------
MultiPhysicsPage::MultiPhysicsPage(QWidget *parent)
     : QWizardPage(parent)
{ 
     setTitle(tr("Multi-physics"));
     setSubTitle(tr("Choose physics and corresponding mesh groups"));
     setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));  

     layout = new QHBoxLayout;
     heatRadioButton = new QRadioButton(tr("heat"));
     fluidRadioButton = new QRadioButton(tr("fluid"));
     layout->addWidget(heatRadioButton);
     layout->addWidget(fluidRadioButton);
     setLayout(layout);
}


//----------------------------------------------------------------------------
// destructor Multi-phsics page
//----------------------------------------------------------------------------
MultiPhysicsPage::~MultiPhysicsPage()
{
     delete layout;
     delete heatRadioButton;
     delete fluidRadioButton;
}


//----------------------------------------------------------------------------
// constructor for material properties of model
//----------------------------------------------------------------------------
MaterialPage::MaterialPage(QWidget *parent)
     : QWizardPage(parent)
{
     setTitle(tr("Material properties"));
     setSubTitle(tr("Specify material properties of the model"));
     setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));

     layout = new QHBoxLayout;
     rhoLabel = new QLabel("rho"); rhoLineEdit = new QLineEdit();
     cLabel = new QLabel("c"); cLineEdit = new QLineEdit();
     qLabel = new QLabel("Q"); qLineEdit = new QLineEdit();
     kLabel = new QLabel("k"); kLineEdit = new QLineEdit();
          
     layout->addWidget(rhoLabel); layout->addWidget(rhoLineEdit); 
     layout->addWidget(cLabel); layout->addWidget(cLineEdit); 
     layout->addWidget(qLabel); layout->addWidget(qLineEdit); 
     layout->addWidget(kLabel); layout->addWidget(kLineEdit); 

     registerField("rho*", rhoLineEdit);
     registerField("c*", cLineEdit);
     registerField("Q*", qLineEdit);
     registerField("k*", kLineEdit);

     setLayout(layout);
}


//----------------------------------------------------------------------------
// destructor for material properties of model
//----------------------------------------------------------------------------
MaterialPage::~MaterialPage()
{
     delete layout;
     
     delete rhoLabel; 
     delete rhoLineEdit;
     delete cLabel; 
     delete cLineEdit;
     delete qLabel; 
     delete qLineEdit;
     delete kLabel; 
     delete kLineEdit;
}


//----------------------------------------------------------------------------
// constructor for boundary conditions page
//----------------------------------------------------------------------------
BoundaryPage::BoundaryPage(BoundaryData *bd, QWidget *parent)
     : QWizardPage(parent)
{
     bdata = bd;

     setTitle(tr("Boundary Conditions"));
     setSubTitle(tr("Specify boundary conditions and corresponding mesh groups"));
     setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));

     layout = new QVBoxLayout;
     title_layout = new QHBoxLayout;
     grp_title = new QLabel(tr("Groups"));
     val_title = new QLabel(tr("Value"));
     bc_title = new QLabel(tr("Boundary Condition"));
     title_layout->addWidget(grp_title);
     title_layout->addWidget(val_title);
     title_layout->addWidget(bc_title);
     layout->addLayout(title_layout);

     hlayouts = new QHBoxLayout*[bdata->numOfGrps];
     labels = new QLabel*[bdata->numOfGrps];
     lineEdits = new QLineEdit*[bdata->numOfGrps];
     comboBoxes = new QComboBox*[bdata->numOfGrps];

     for(int i=0;i<bdata->numOfGrps;i++){
       hlayouts[i] = new QHBoxLayout;
       labels[i] = new QLabel(QString::number(bdata->groups[i]));
       comboBoxes[i] = new QComboBox();
       comboBoxes[i]->addItem("");
       comboBoxes[i]->addItem("Specified Temperature");
       comboBoxes[i]->addItem("Heat flux");
       lineEdits[i] = new QLineEdit();
       hlayouts[i]->addWidget(labels[i]);
       hlayouts[i]->addWidget(comboBoxes[i]);
       hlayouts[i]->addWidget(lineEdits[i]);
       layout->addLayout(hlayouts[i]);
     }

     saveButton = new QPushButton("Save Boundary Conditions");
     connect(saveButton,SIGNAL(pressed()),this,SLOT(save()));
     layout->addWidget(saveButton);

     setLayout(layout);
}


//----------------------------------------------------------------------------
// constructor for boundary conditions page
//----------------------------------------------------------------------------
BoundaryPage::~BoundaryPage()
{
     for(int i=0;i<bdata->numOfGrps;i++){
       delete hlayouts[i];
       delete labels[i];
       delete lineEdits[i];
       delete comboBoxes[i];
     }
 
     delete[] hlayouts;
     delete[] labels;
     delete[] lineEdits;
     delete[] comboBoxes;

     delete layout;
     delete title_layout;
     delete grp_title;
     delete val_title;
     delete bc_title;
     delete saveButton;
}


void BoundaryPage::save()
{
    for(int i=0;i<bdata->numOfGrps;i++){
      bdata->types[i] = comboBoxes[i]->currentIndex();
      bdata->values[i] = (lineEdits[i]->text()).toDouble();
    }
}
    

//----------------------------------------------------------------------------
// constructor for launch model page
//----------------------------------------------------------------------------
LaunchPage::LaunchPage(QWidget *parent)
     : QWizardPage(parent)
{
     setTitle(tr("Launch Model"));
     setSubTitle(tr("Model setup complete. Press Finish to launch model"));
     setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));
}


//----------------------------------------------------------------------------
// destructor for launch model page
//----------------------------------------------------------------------------
LaunchPage::~LaunchPage()
{

}
