#include "Panel_dynamics.h"

#include "Panel_monitors.h"
#include "Program_title.h"
#include "MD_simulator.h"
#include "Simulator_factory.h"
#include "Project.h"
#include "Initialization_stage.h"
#include "Timer.h"
#include "Thermostat.h"
#include "Model_kit.h"
#include "Lock.h"
#include "Mach_eps.h"
#include "Profiler.h"
#include "Pressure_unit.h"
#include "System_of_Units.h"
#include "MTS_MD.h"
#include "MTS_VV.h"
#include "MTS_VP.h"
#include "rRESPA_4.h"
#include "Shuffled.h"
#include "Berendsen_barostat.h"
#include "Mass.h"
#include "Panel_performance.h"

#include "Log.h"
#include "User.h"
#include "Main_window.h"

#include <QCloseEvent>

namespace MM
{   

Panel_dynamics::
Panel_dynamics ()
:
    Panel ("Dynamics", "left"),
    player_(Main_window::singleton())
{
    setupUi (this);

#ifndef ASCALAPH
    //Tool->removeItem (Tool->findText("MDynaMix"));
    Tool->hide();
#else
    //comboBox_Integrator->removeItem (comboBox_Integrator->findText("MTS VP"));
    //comboBox_Integrator->removeItem (comboBox_Integrator->findText("MTS VV"));
//    comboBox_Integrator->removeItem (comboBox_Integrator->findText("MTS"));
#endif
    comboBox_Integrator->removeItem (comboBox_Integrator->findText("HMC"));
    comboBox_Integrator->removeItem (comboBox_Integrator->findText("Shuffled"));
    comboBox_Integrator->removeItem (comboBox_Integrator->findText("MTS"));

    pushButton_Options->hide();
    checkBox_Elaborated->hide();

    connect(Tool,           SIGNAL(currentIndexChanged (const QString &)),
            this,           SLOT(set_tool (const QString &)));


    connect(comboBox_Integrator, SIGNAL(currentIndexChanged (const QString&)),
            this,                SLOT(set_integrator (const QString &)));

    connect(spinBox_Inner_steps,    SIGNAL(valueChanged   (int)),
            this,                   SLOT(set_inner_steps  (int)));
    connect(spinBox_Inner_steps_2,  SIGNAL(valueChanged   (int)),
            this,                   SLOT(set_inner_steps_2(int)));
    connect(spinBox_Inner_steps_3,  SIGNAL(valueChanged   (int)),
            this,                   SLOT(set_inner_steps_3(int)));

    connect(doubleSpinBox_R,        SIGNAL(valueChanged   (double)),
            this,                   SLOT(set_R  (double)));
    connect(doubleSpinBox_R_2,      SIGNAL(valueChanged   (double)),
            this,                   SLOT(set_R_2(double)));
    //connect(doubleSpinBox_R_3,      SIGNAL(valueChanged   (double)),
    //        this,                   SLOT(set_R_3(double)));

    connect(checkBox_Barostat,          SIGNAL(stateChanged (int)),
            this,                       SLOT(barostat     (int)));

    connect(doubleSpinBox_Pressure,     SIGNAL(valueChanged (double)),
            this,                       SLOT(set_pressure(double)));
       
    connect(doubleSpinBox_Barostat_Tau, SIGNAL(valueChanged (double)),
            this,                       SLOT(set_barostat_Tau(double)));
       



    connect(checkBox_Thermostat,        SIGNAL(stateChanged (int)),
            this,                       SLOT(thermostat     (int)));

    connect (comboBox_Thermostat, SIGNAL(currentIndexChanged(const QString&)),
             this,                SLOT  (show_thermostat    (const QString&)));


    
    connect(doubleSpinBox_Temperature,  SIGNAL(valueChanged (double)),
            this,                       SLOT(set_temperature(double)));
       

    connect(doubleSpinBox_Time_per_long_step,  SIGNAL(valueChanged (double)),
            this,                       SLOT(set_steps(double)));
       
    connect(doubleSpinBox_Duration,     SIGNAL(valueChanged (double)),
            this,                       SLOT(set_steps(double)));


    connect(toolButtonv_Integrator,     SIGNAL(toggled (bool)),
            this,                       SLOT(integrator_full_control (bool)));
    connect(toolButtonv_Barostat,       SIGNAL(toggled (bool)),
            this,                       SLOT(barostat_full_control (bool)));
    connect(toolButtonv_Thermostat,     SIGNAL(toggled (bool)),
            this,                       SLOT(thermostat_full_control (bool)));

    connect(checkBox_Elaborated,        SIGNAL(stateChanged (int)),
            this,                       SLOT(check_full_control (int)));
    check_full_control (0);

    connect(doubleSpinBox_Tau,          SIGNAL(valueChanged (double)), 
            this,                       SLOT(set_response_constant(double)));
    connect(doubleSpinBox_Nu,           SIGNAL(valueChanged (double)), 
            this,                       SLOT(set_response_constant(double)));
    connect(doubleSpinBox_Nu_Lowe,      SIGNAL(valueChanged (double)), 
            this,                       SLOT(set_response_constant(double)));
       
    connect(checkBox_min_mass,          SIGNAL(stateChanged (int)), 
            this,                       SLOT(turn_min_mass(int)));
    connect(doubleSpinBox_min_mass,     SIGNAL(valueChanged (double)), 
            this,                       SLOT(set_min_mass(double)));
       
    renew ();
}

void Panel_dynamics::
set_stop_state ()
{
    player_->player_on_ = false;

    player_->toolButton_Stop   -> setEnabled (false);
    player_->toolButton_Tune   -> setEnabled (true);
    player_->toolButton_Run    -> setEnabled (true);
    player_->toolButton_Start  -> setEnabled (true);

    if (this->isHidden ())
        turn (false);
}

void Panel_dynamics::
set_run_state ()
{
    player_->player_on_ = true;

    player_->toolButton_Stop   -> setEnabled (true);
    player_->toolButton_Tune   -> setEnabled (false);
    player_->toolButton_Run    -> setEnabled (false);
    player_->toolButton_Start  -> setEnabled (false);
}

void Panel_dynamics::
turn (bool on)
{
    //MD_simulator & simulator = model().kit().current_MD();

    //if (!simulator.is_running())
    if (!player_->player_on_)
    {
        player_->toolButton_Stop   -> disconnect ();
        player_->toolButton_Back   -> disconnect ();
        player_->toolButton_Tune   -> disconnect ();
        player_->toolButton_Run    -> disconnect ();
        player_->toolButton_Start  -> disconnect ();
        player_->toolButton_Forward-> disconnect ();
        player_->toolButton_Pause  -> disconnect ();

        if (on)
        {
            player_->tabWidget_bottom->setCurrentWidget (player_->tab_Run);

            connect (player_->toolButton_Stop,   SIGNAL(clicked()), this,
                                 SLOT  (stop   ()));
            connect (player_->toolButton_Tune,   SIGNAL(clicked()), this,
                                 SLOT  (tune   ()));
            connect (player_->toolButton_Run,    SIGNAL(clicked()), this,
                                 SLOT  (run    ()));
            connect (player_->toolButton_Start,  SIGNAL(clicked()), this,
                                 SLOT  (start  ()));
            set_stop_state ();

            if (Panel_monitors::exist())
                Panel_monitors::singleton()->renew(Model_event::Monitors_changed);
        }
        else 
        {
            player_->toolButton_Stop   -> setEnabled (false);
            player_->toolButton_Back   -> setEnabled (false);
            player_->toolButton_Tune   -> setEnabled (false);
            player_->toolButton_Run    -> setEnabled (false);
            player_->toolButton_Start  -> setEnabled (false);
            player_->toolButton_Forward-> setEnabled (false);
            player_->toolButton_Pause  -> setEnabled (false);
        }
    }

    if (on)
    {
        if (&model().kit().simulator() != &model().kit().MD() 
#ifdef M_DYNAMIX
			||
            &model().kit().simulator() != &model().kit().MDynaMix()
#endif
			)
            set_tool (Tool->currentText());

        renew ();
    }
}

void Panel_dynamics::
closeEvent (QCloseEvent * event)
{
    Simulator & simulator = model().kit().simulator();

    if (simulator.is_running())
        event->ignore ();
}

void Panel_dynamics::
set_tool (const QString & text)
{
    //Text tool(text);

    //if (text == "Ascalaph")
    //    tool = "MD";

    //MD_simulator::adopt (dynamic_cast <MD_simulator*> 
    //    (Simulator_factory::create (tool)));

    if (text == "Ascalaph MD")
        model().kit().set_simulator (model().kit().MD ());

    #ifdef M_DYNAMIX
    else if (text == "MDynaMix")
        model().kit().set_simulator (model().kit().MDynaMix ());
    #endif

    if (Panel_monitors::exist())
        Panel_monitors::singleton()->renew(Model_event::Monitors_changed);

    renew ();
}

void Panel_dynamics::
set_integrator (const QString & text)
{
    MD_simulator & md = model().kit().MD();
    
    if (text == "MTS")
        md.set_method ("MTS_MD");

    else if (text == "rRESPA 4")
        md.set_method ("rRESPA_4");

    else if (text == "HMC")
        md.set_method ("HMC");

    else if (text == "Shuffled")
        md.set_method ("Shuffled");

    else if (text == "MTS VP")
        md.set_method ("MTS_VP");

    else if (text == "MTS VV")
        md.set_method ("MTS_VV");

    else if (text == "OPVL")
        md.set_method ("OPVL");

    else if (text == "OVVL")
        md.set_method ("OVVL");

    else if (text == "PEFRL")
        md.set_method ("PEFRL");

    else if (text == "VEFRL")
        md.set_method ("VEFRL");

    else if (text == "Position leapfrog")
        md.set_method ("Position_leapfrog");

    else if (text == "Velocity leapfrog")
        md.set_method ("Velocity_leapfrog");

    else if (text == "Position Verlet")
        md.set_method ("Position_verlet");

    else if (text == "Velocity Verlet")
        md.set_method ("Velocity_verlet");

    else if (text == "Euler")
        md.set_method ("Classic_Euler");
    else if (text == "Euler-P")
        md.set_method ("Position_Euler");
    else if (text == "Euler-V")
        md.set_method ("Velocity_Euler");

    renew ();

    if (Panel_performance::exist ())
        Panel_performance::singleton()->renew_values ();
}

void Panel_dynamics::
set_inner_steps (int v)
{
    MTS & method = dynamic_cast<MTS &>(model().kit().MD().method());
    method.set_inner_steps (v);
}
void Panel_dynamics::
set_inner_steps_2 (int v)
{
    rRESPA_4 * method = dynamic_cast<rRESPA_4 *>(&model().kit().MD().method());
    if (method != 0)
        method->set_inner_steps_2 (v);
    else
    {
        MTS *one_step_method = dynamic_cast<MTS *>(&model().kit().MD().method());
        one_step_method->set_inner_steps (v);
    }
}
void Panel_dynamics::
set_inner_steps_3 (int v)
{
    rRESPA_4 & method = dynamic_cast<rRESPA_4 &>(model().kit().MD().method());
    method.set_inner_steps_3 (v);
}

void Panel_dynamics::
set_R (double v)
{

    MTS & method = dynamic_cast<MTS &>(model().kit().MD().method());
    method.set_R (v);
}
void Panel_dynamics::
set_R_2 (double v)
{
    rRESPA_4 & method = dynamic_cast<rRESPA_4 &>(model().kit().MD().method());
    method.set_R2 (v);
}
//void Panel_dynamics::
//set_R_3 (double v)
//{
//    rRESPA_4 & method = dynamic_cast<rRESPA_4 &>(model().kit().MD().method());
//    method.set_inner_steps_3 (v);
//}

void Panel_dynamics::
barostat (int on)
{
//    doubleSpinBox_Pressure->setEnabled   (on);
    model().kit().simulator().set_barostat (on);
    renew ();
}
void Panel_dynamics::
set_pressure (double value)
{
    Pressure_unit unit;
    unit.set_atm (value);
    double p = System_of_Units::singleton().pressure (unit);
    model().kit().simulator().set_desired_pressure (p);
}
void Panel_dynamics::
set_barostat_Tau (double Tau)
{
    Duration_unit unit;
    unit.set_ps (Tau);
    Berendsen_barostat & barostat = 
        dynamic_cast <Berendsen_barostat &> (model().kit().MD().barostat());
    barostat.set_time_constant (unit);
}

void Panel_dynamics::
thermostat (int on)
{
//    doubleSpinBox_Temperature->setEnabled    (on);
    model().kit().simulator().set_thermostat (on);
    renew ();
}

void Panel_dynamics::
set_temperature (double value)
{
    Temperature_unit t;
    t.set_K (value);
    model().kit().simulator().set_desired_temperature (t);
}

void Panel_dynamics::
set_steps (double)
{
    Duration_unit duration;
    duration.set_step_length_ps (doubleSpinBox_Time_per_long_step->value()/1000.);
    duration.set_ps             (doubleSpinBox_Duration->value());
    model().kit().simulator().set_duration (duration);
}

void Panel_dynamics::
set_response_constant(double v)
{
    model().kit().MD().thermostat().set_response_constant (v);
}

void Panel_dynamics::
renew_current_model (Model &)
{
    renew ();
}

void Panel_dynamics::
renew (Model_event::Hint /*hint*/)
{
    Simulator & simulator = model().kit().simulator();
    MD_simulator & md = model().kit().MD();
    Text const & tool_name = simulator.title();

    //check_full_control (0);

    if (tool_name == "MD")
        Tool->setCurrentIndex (Tool->findText("Ascalaph MD"));

    else if (tool_name == "MDynaMix")
        Tool->setCurrentIndex (Tool->findText("MDynaMix"));
    else
        FLAW (tool_name + " - no such tool.");

    char const * method_name = md.method_name ();
    int index = comboBox_Integrator->findText (method_name);
    comboBox_Integrator->blockSignals (true);
    comboBox_Integrator->setCurrentIndex (index);
    comboBox_Integrator->blockSignals (false);

    label_inner_steps    ->hide();
    label_inner_steps_2  ->hide();
    label_inner_steps_3  ->hide();
    spinBox_Inner_steps  ->hide();
    spinBox_Inner_steps_2->hide();
    spinBox_Inner_steps_3->hide();
    doubleSpinBox_R      ->hide();
    doubleSpinBox_R_2    ->hide();
    QString integrator = comboBox_Integrator->currentText();

    if (integrator == "MTS")
    {
        label_Integrator->setText ("Multiple time step");
        groupBox_Inner_steps->show();
        label_inner_steps  ->show();
        spinBox_Inner_steps->show();
        MTS & method = dynamic_cast<MTS &>(md.method());
        
        spinBox_Inner_steps->blockSignals (true);
        spinBox_Inner_steps->setValue (method.inner_steps());
        spinBox_Inner_steps->blockSignals (false);
    }

    else if (integrator == "HMC")
        label_Integrator->setText ("HMC");

    else if (integrator == "Shuffled")
        label_Integrator->setText ("Shuffled");

    else if (integrator == "rRESPA 4")
    {
        label_Integrator->setText ("rRESPA 4-level");
        groupBox_Inner_steps->show();
        label_inner_steps    ->show();
        label_inner_steps_2  ->show();
        label_inner_steps_3  ->show();
        spinBox_Inner_steps  ->show();
        spinBox_Inner_steps_2->show();
        spinBox_Inner_steps_3->show();
        doubleSpinBox_R      ->show();
        doubleSpinBox_R_2    ->show();

        rRESPA_4 & method = dynamic_cast<rRESPA_4 &>(md.method());

        spinBox_Inner_steps  ->blockSignals (true);
        spinBox_Inner_steps_2->blockSignals (true);
        spinBox_Inner_steps_3->blockSignals (true);
        doubleSpinBox_R      ->blockSignals (true);
        doubleSpinBox_R_2    ->blockSignals (true);
        
        spinBox_Inner_steps  ->setValue (method.inner_steps());
        spinBox_Inner_steps_2->setValue (method.inner_steps_2());
        spinBox_Inner_steps_3->setValue (method.inner_steps_3());
        doubleSpinBox_R      ->setValue (method.R());
        doubleSpinBox_R_2    ->setValue (method.R2());
        //doubleSpinBox_R_3    ->setValue (method.inner_steps_3());

        spinBox_Inner_steps  ->blockSignals (false);
        spinBox_Inner_steps_2->blockSignals (false);
        spinBox_Inner_steps_3->blockSignals (false);
        doubleSpinBox_R      ->blockSignals (false);
        doubleSpinBox_R_2    ->blockSignals (false);
    }
    
    else if (integrator == "MTS VV")
    {
        label_Integrator->setText ("Multiple time step");
        groupBox_Inner_steps->show();
        spinBox_Inner_steps_2->show();
        doubleSpinBox_R      ->show();

        MTS_VV & method = dynamic_cast<MTS_VV &>(md.method());
        
        spinBox_Inner_steps_2   ->blockSignals (true);
        doubleSpinBox_R         ->blockSignals (true);
        spinBox_Inner_steps_2   ->setValue (method.inner_steps());
        doubleSpinBox_R         ->setValue (method.R());
        spinBox_Inner_steps_2   ->blockSignals (false);
        doubleSpinBox_R         ->blockSignals (false);
    }
    
    else if (integrator == "MTS VP")
    {
        label_Integrator->setText ("Multiple time step");
        groupBox_Inner_steps->show();
        spinBox_Inner_steps_2->show();
        doubleSpinBox_R      ->show();

        MTS_VP & method = dynamic_cast<MTS_VP &>(md.method());
        
        spinBox_Inner_steps_2   ->blockSignals (true);
        doubleSpinBox_R         ->blockSignals (true);
        spinBox_Inner_steps_2   ->setValue (method.inner_steps());
        doubleSpinBox_R         ->setValue (method.R());
        spinBox_Inner_steps_2   ->blockSignals (false);
        doubleSpinBox_R         ->blockSignals (false);
    }
    
    else if (integrator == "OPVL")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Optimized Position Verlet-Like");
    }
    else if (integrator == "OVVL")
    {    
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Optimized Velocity Verlet-Like");
    }
    else if (integrator == "PEFRL")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Position Extended Forest-Ruth-Like");
    }    
    else if (integrator == "VEFRL")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Velocity Extended Forest-Ruth-Like");
    }    
    else if (integrator == "Position leapfrog")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("");
    }    
    else if (integrator == "Velocity leapfrog")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("");
    }    
    else if (integrator == "Position Verlet")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("");
    }    
    else if (integrator == "Velocity Verlet")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("");
    }
    else if (integrator == "Euler")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Classic Euler");
    }
    else if (integrator == "Euler-P")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Position Euler");
    }
    else if (integrator == "Euler-V")
    {
        groupBox_Inner_steps ->hide();
        label_Integrator->setText ("Velocity Euler");
    }


    bool support_barostat = simulator.support_barostat();

    if (support_barostat)
    {
        static Pressure_unit unit;
        System_of_Units::singleton().set_pressure (unit, simulator.desired_pressure());

        groupBox_Barostat->setEnabled (true);
        doubleSpinBox_Pressure->setValue (unit.atm());

        bool has_barostat = simulator.has_barostat();

        checkBox_Barostat->blockSignals (true);
        checkBox_Barostat->setChecked (has_barostat);
        checkBox_Barostat->blockSignals (false);

        if (has_barostat)
        {
            doubleSpinBox_Pressure->setEnabled (true);
            checkBox_Barostat->setChecked (true);

            doubleSpinBox_Barostat_Tau->setEnabled (true);
            Duration_unit Tau;
            dynamic_cast<Berendsen_barostat&>(md.barostat()).get_time_constant (Tau);
            doubleSpinBox_Barostat_Tau->blockSignals (true);
            doubleSpinBox_Barostat_Tau->setValue (Tau.ps());
            doubleSpinBox_Barostat_Tau->blockSignals (false);
        }
        else
        {
            doubleSpinBox_Pressure->setEnabled (false);
            checkBox_Barostat->setChecked (false);
            doubleSpinBox_Barostat_Tau->setEnabled (false);
            doubleSpinBox_Barostat_Tau->blockSignals (true);
            doubleSpinBox_Barostat_Tau->setValue (0);
            doubleSpinBox_Barostat_Tau->blockSignals (false);
        }
   }
    else
        groupBox_Barostat->setEnabled (false);


    bool has_thermostat = simulator.has_thermostat();

    checkBox_Thermostat->setCheckState 
        (has_thermostat ? Qt::Checked : Qt::Unchecked);

    doubleSpinBox_Temperature->setEnabled    (has_thermostat);
    stackedWidget_Thermostat ->setEnabled    (has_thermostat);

    if (has_thermostat)
    {
        Text type = md.thermostat().title ();
        int index = comboBox_Thermostat->findText (type);
        comboBox_Thermostat->blockSignals (true);
        comboBox_Thermostat->setCurrentIndex (index);
        comboBox_Thermostat->blockSignals (false);
        //to_user().status (type);
        //doubleSpinBox_Temperature->setValue (simulator.desired_temperature ().K());

        doubleSpinBox_Tau     ->blockSignals (true);
        doubleSpinBox_Nu      ->blockSignals (true);
        doubleSpinBox_Nu_Lowe ->blockSignals (true);
        double response_constant = md.thermostat().response_constant ();
        doubleSpinBox_Tau     ->setValue (response_constant);
        doubleSpinBox_Nu      ->setValue (response_constant);
        doubleSpinBox_Nu_Lowe ->setValue (response_constant);
        doubleSpinBox_Tau     ->blockSignals (false);
        doubleSpinBox_Nu      ->blockSignals (false);
        doubleSpinBox_Nu_Lowe ->blockSignals (false);
    }

    //fix to unit viewer
    doubleSpinBox_Temperature->setValue 
        (simulator.desired_temperature().K());

    doubleSpinBox_Time_per_long_step->blockSignals (true);
    doubleSpinBox_Duration->blockSignals (true);

    Duration_unit duration = simulator.duration();
    doubleSpinBox_Time_per_long_step->setValue (duration.step_length_ps() * 1000.);
    doubleSpinBox_Duration->          setValue (duration.ps() + d_mach_eps_2);

    doubleSpinBox_Duration->blockSignals (false);
    doubleSpinBox_Time_per_long_step->blockSignals (false);

    checkBox_min_mass->setCheckState 
        (Mass::has_minimal () ? Qt::Checked : Qt::Unchecked);
    doubleSpinBox_min_mass->setValue (Mass::minimal());
    doubleSpinBox_min_mass->setEnabled (Mass::has_minimal ());
}

void Panel_dynamics::
show_thermostat (const QString & type)
{
    MD_simulator & md = model().kit().MD();
    md.set_thermostat (Text(type).c_str());
    
    for (int i=0;  i<stackedWidget_Thermostat->count();  ++i)
    {
        if (stackedWidget_Thermostat->widget(i)->objectName() == type)
            stackedWidget_Thermostat->setCurrentIndex (i);
    }
    renew();
}

void Panel_dynamics::
check_full_control (int)
{
    full_control (checkBox_Elaborated->isChecked() && Tool->currentText() != "MDynaMix");
}

void Panel_dynamics::
integrator_full_control (bool on)
{
    if (on)
    {
        frame_Integrator   ->show();
    }
    else
    {
        frame_Integrator   ->hide();
    }
}

void Panel_dynamics::
barostat_full_control (bool on)
{
    if (on)
    {
        label_Barostat_Tau          ->show();
        doubleSpinBox_Barostat_Tau  ->show();
        label_Barostat              ->show();
    }
    else
    {
        label_Barostat_Tau          ->hide();
        doubleSpinBox_Barostat_Tau  ->hide();
        label_Barostat              ->hide();
    }
}

void Panel_dynamics::
thermostat_full_control (bool on)
{
    if (on)
    {
        stackedWidget_Thermostat    ->show();
        comboBox_Thermostat         ->show();
        checkBox_Renew_velocities   ->show();
    }
    else
    {
        stackedWidget_Thermostat    ->hide();
        comboBox_Thermostat         ->hide();
        checkBox_Renew_velocities   ->hide();
    }
}

void Panel_dynamics::
full_control (bool on)
{
    if (on)
    {
        //groupBox_Integrator         ->show();
        frame_Integrator   ->show();

        label_Barostat_Tau          ->show();
        doubleSpinBox_Barostat_Tau  ->show();
        label_Barostat              ->show();

        stackedWidget_Thermostat    ->show();
        comboBox_Thermostat         ->show();
    }
    else
    {
        //groupBox_Integrator         ->hide();
        frame_Integrator   ->hide();

        label_Barostat_Tau          ->hide();
        doubleSpinBox_Barostat_Tau  ->hide();
        label_Barostat              ->hide();

        stackedWidget_Thermostat    ->hide();
        comboBox_Thermostat         ->hide();
    }
}

void Panel_dynamics::turn_min_mass (int on) {Mass::set_has_minimal (on); renew();}
void Panel_dynamics::set_min_mass (double v){Mass::set_minimal (v);}

void Panel_dynamics::
run ()
{
    tune  ();
    start ();
}

void Panel_dynamics::
tune ()
{
    Simulator & simulator = model().kit().simulator();
    //Model        & model     = Project::singleton().current_model();//fix
    
    //simulator.set_model (model());//fix
    
    //simulator.set_steps (doubleSpinBox_Duration->value());  //fix to connect

    struct Process_events : public Command
    {
        int i_;

        Process_events () : i_(0) {}

        void execute () 
        {
            if (++i_ % 1 == 0)
            {
                //qApp->processEvents (QEventLoop::AllEvents, 100);
                qApp->processEvents(QEventLoop::ExcludeSocketNotifiers);

                //if (Panel_monitors::exist())
                //    Panel_monitors::singleton()->renew_values();
            }
        }
    };
    simulator.after_each_step (new Process_events);

    model().kit().strip (true);

    if (checkBox_Renew_velocities->checkState() == Qt::Checked)
    {
        Temperature_unit t;
        t.set_K (doubleSpinBox_Temperature->value());
        Initialization_stage::setup_velocities (model(), t);
    }

    simulator.tune ();

    to_user().status ("Ready to run");
}

Simulator * simulator = 0; //fix

void Panel_dynamics::
start ()
{
    Simulator & simulator = model().kit().simulator();
    MM::simulator = & simulator;
    Timer timer;
    Text  time;

    //fix 
    //model().kit().interaction ().set_lock (true);
    //Lock <Interaction> lock (model().kit().interaction ());

    to_user().status ("Started");

    profile().restart();

    set_run_state ();
    
    try
    {
        simulator.start ();
    }
    catch(Text & message)   {stop (); to_user().error (message);}
    catch(Flaw & exception) {stop (); to_user().error (exception.message());}
    catch(Contract_violation & exc) {stop (); to_user().error (exc.message());}
    catch(...)              {stop (); 
        to_user().fatal_error ("Panel_dynamics::start Unknown error.");}

    set_stop_state ();

    //model().kit().interaction ().report (&time, "F speed");
    profile().report();

    time += "run ";
    time += timer.elapsed();    timer.restart();
    time += " sec\n";
    log () << time;

    to_user().status("Finish");
}

void Panel_dynamics::
stop ()
{
    if (MM::simulator != 0)
        MM::simulator->stop ();
    //MM::simulator = 0;

    if (model().kit().simulator().title() == "MDynaMix") 
        to_user ().info ("Stopped by the user. "
            "Please wait for the end of trajectory reading.");

    to_user().status("Stop");
}

}//MM
