#ifndef M_DYNAMIX_INPUT_H
#define M_DYNAMIX_INPUT_H

#ifndef DBC_H
#include "DbC.h"
#endif

#ifndef TEXT_H
#include "Text.h"
#endif

#ifndef TEXT_OUTPUT_H
#include "Text_output.h"
#endif

#ifndef M_DYNAMIX_MOLECULAR_TYPE_H
#include "M_DynaMix_molecular_type.h"
#endif

#ifndef ARRAY_H
#include "Array.h"
#endif

#ifndef DURATION_UNIT_H
#include "Duration_unit.h"
#endif

//#include "Own.h"

#include <iosfwd>
#include <string>

namespace MM
{
class Model;

class M_DynaMix_input : public DbC
{
    Model *                 model_;

    Duration_unit           time_step_;
public:  //fix
    friend class Form_M_DynaMix;

    //enum Boundary_conditions    {vacuum, box};
    //enum Box_type               {manual, from_crystal, automatic};
    Model &                 model ()                    {return *model_;}
    Model const &           model () const              {return *model_;}
    void                    set_model (Model &model)    {model_= &model;}

    Duration_unit           time_step () const;
    void                    set_time_step (Duration_unit l);

    Text                                source_file_name_;
//    Own <Text_output>   out_;

    int                     output_control_;
//    Text                    input_file_name_;
//    Text                  output_file_name_;
    std::string             main_file_name_;
    std::string             molecular_database_path_;
    bool                    read_from_restart_file_;

    bool                    dump_restart_file_;
    bool                    check_only_;
    bool                    zero_counter_of_cpu_time_;

    bool                    constant_temperature_;
    bool                    constant_pressure_;
    bool                    anizotropic_NPT_;
    
    Array <M_DynaMix_molecular_type>    molecular_types_;
    
    double                  temperature_;
    double                  density_;
    double                  pressure_;
    //double                  box_x_;
    //double                  box_y_;
    //double                  box_z_;
    int                     cell_type_;
    //Boundary_conditions     boundary_conditions_;
    //Box_type                box_type_;
    
    int                     small_steps_in_one_long_;
    //int                     total_long_steps_;
    int                     steps_for_intermediate_averaging_;
    int                     take_averages_each___steps_;
    int                     dump_restart_file_after___steps_;

    double                  t_termostat_;
    double                  p_termostat_;
    bool                    is_simple_velosity_scaling_;
    double                  delta_t_;

    double                  r_cutoff_;
    double                  r_cutoff_fast_force_;
    int                     check_neigbours_after___step_;
    
    double                  alpha_r_;
    double                  fexp_;
    
    bool                    recalculate_list_of_intramolecular_interactions_;

    bool                    constrain_dynamics_;
    double                  tolerance_parameter_;
    
    int                     initial_state_;
    bool                    set_velocities_to_0_;
    double                  hole_radius_;
    bool                    keep_initial_configuration_;
    double                  permissible_deviation_;
    Text                    file_name_;

    bool                    change_temperature_at_restart_;
    bool                    change_density_at_restart_;

    int                     final_averaging_after___intermediate_averaging_;
    bool                    dump_XMOL_config_file_;

    bool                    cut_large_forces_;
    double                  max_level_of_large_forces_;

    bool                    calculate_RDF_;
    bool                    dump_RDF_;
    bool                    read_restart_RDF_file_;
    bool                    is_RDF_for_all_sites_;
    double                  cutoff_RDF_;
    int                     RDF_resolution_;

    int                     dump_trajectory_format_;
    double                  dump_trajectory_interval_;
    int                     number_of_config_in_a_trajectory_;

    bool                    calculate_tcf_;
    bool                    restart_tcf_;
    bool                    dump_tsf_;
    int                     NSTEG_;
    int                     JUMP_;

public:
    explicit        M_DynaMix_input (Model & model);
    
//    const Text &        file_name () const              {return file_name_;}
    void            prepare_input   (Text_output & out); //fix Model &model
    void            prepare_input_5 (Text_output & out);
    void            load (const Text & file_name);
    
//protected:
    void            setup_dependency ();
    void            set_vacuum ();
    void            set_box    ();
    double          box_x ();
    double          box_y ();
    double          box_z ();

    void            write_output_control   (Text_output & out);

    const Text &    source_file_name       ()       {return source_file_name_;}
    Text            input_file_name        ()       {return main_file_name() + ".start";}

    void                write_output_file_name (Text_output & out);
    //const std::string & output_file_name   () const {return output_file_name_;}
    //Text output_file_name   () const {return Text(main_file_name_.c_str());}
    Text main_file_name    () const {return Text(main_file_name_.c_str());}
    
    void write_molecular_database_path                      (Text_output & out);

    bool read_from_restart_file ()             {return read_from_restart_file_;}
    void set_read_from_restart_file (bool value){read_from_restart_file_=value;}
    void write_read_from_restart_file (Text_output & out);

    void write_dump_restart_file                            (Text_output & out);

    bool check_only ()                       {return check_only_;}
    void set_check_only (bool value)         {check_only_ = value;}
    void write_check_only                    (Text_output & out);

    void write_zero_counter_of_cpu_time                     (Text_output & out);
    void write_type_of_statistical_ensemble                 (Text_output & out);
    void write_number_of_molecular_types                    (Text_output & out);

    void write_molecular_types               (Text_output & out);
    void erase_molecular_types               ();
    void add_molecular_type                  (M_DynaMix_molecular_type &);
    void increment_molecular_type            (const Text & type);

    void write_number_of_molecules                          (Text_output & out);
    void write_nonbonded_intramolecular_interactions        (Text_output & out);
    void write_interactions_1_4                             (Text_output & out);
    void write_scaling_factors_for_1_4_LJ                   (Text_output & out);
    void write_scaling_factors_for_1_4_electrostatics       (Text_output & out);
    void write_intramolecular_potential_type                (Text_output & out);
    void write_rules_for_initial_box_size_or_density        (Text_output & out);
    void write_time_steps                                   (Text_output & out);
    void write_nose_termostat_parameters                    (Text_output & out);
    void write_cut_offs                                     (Text_output & out);
    void write_ewald_parameters                             (Text_output & out);
    void write_which_of_the_molecules_move                  (Text_output & out);
    void write_recalculate_list_of_intramolecular_interactions(Text_output&out);
    void write_constrain_dynamics                           (Text_output & out);
    void write_initial_state                                (Text_output & out);
    void write_initial_states_for_atom_group_types          (Text_output & out);
    void write_initial_state_configuration                  (Text_output & out);
    void write_change_temparature_or_density_after_restart  (Text_output & out);
    void write_final_averaging                              (Text_output & out);
    void write_cut_large_forces                             (Text_output & out);
    void write_RDFs                                         (Text_output & out);
    void write_dump_trajectory                              (Text_output & out);
    void write_TCF_calculations                             (Text_output & out);
    void write_optional_parameters                          (Text_output & out);
    void write_RDFs_additional                              (Text_output & out);

private:
    int             line_counter_;

    bool            next_line (std::ifstream & in, std::string & line);
};

}//MM

#endif //M_DYNAMIX_INPUT_H

