#include "Graphic_configuration.h"

#include "Panel_monitors.h"
#include "Panel_about.h"
#include "Panel_move_model.h"
#include "Panel_add_model.h"
#include "Panel_select.h"
#include "Panel_geometry.h"
#include "Panel_sequence.h"
#include "Panel_protocol.h"

#include "Abstracts.h"
#include "Prototype_repository.h"
//#include "Any_ptr.h"

#include "Path.h"
#include "Main_window.h"
#include "Main_window_user.h"
#include "Model_RM_window.h"
#include "Model_RM_widget.h"
#include "Information.h"
#include "New_model_Qt.h"

//#include "Form_main_window_user.h"
#include "Qt_interface.h"
//#include "Qt_text_output.h"
#include "Add_model_dialog.h"
//#include "SoQt_application.h"
//#include "MolMeccano_application.h"
#include "Model.h"
#include "Project.h"
#include "Model_kit.h"
//#include "Qt_simulation_task.h"
//#include "Atom.h"
///#include "Atom_impl.h"

//#include "Molecule_impl.h"
///#include "Default_id.h"
//#include "Inventor_atom_attributes.h"
#include "Default_component.h"
//#include "Default_bond.h"

#include "Qt_open.h"
#include "Qt_add.h"
#include "Qt_pull_on.h"
#include "Current_folder.h"
#include "Qt_save_as.h"
#include "Qt_save.h"
#include "Qt_save_all.h"

//#include "Model_impl.h"
//#include "Model_manager_impl.h"

//#include <qwidget.h>
#include "Project_impl.h"
#include "No_protocol_view.h"

//#include "Form_protocol.h"
//#include "Qt_protocol_view.h"

//#include "Form_monitors.h"
//#include "Form_information.h"
//#include "Form_geometry.h"
//#include "Form_add_model.h"

#include <QFileInfo>
#include <QDesktopServices>

namespace MM
{
//Text application_name;      //fix move to application

Graphic_configuration::
Graphic_configuration (int argc, char * argv[])
:
    Configuration (argc, argv)
{
    Prototype_repository & repository = Prototype_repository::singleton();

    repository.adopt ((Protocol_view*)  new No_protocol_view());
    repository.adopt ((Project*)        new Project_impl());
    repository.adopt ((User*)           new Main_window_user());
    repository.adopt ((User_interface*) new Qt_interface());

    repository.adopt ((New_model_impl*) new New_model_Qt());


///    repository.adopt ((ID*)             new Default_id());
    
///    Atom_impl *atom = new Atom_impl (Element("C"));
///    atom->kit().add_hyperchem_attributes (new Hyperchem_attributes(*atom)); //fix
///    repository.adopt ((Atom*) atom);

    class Qt_add_model_dialog : public Add_model_dialog
    {
        void execute () 
        {
            Panel_move_model::singleton()->popup ();
            Panel_add_model ::singleton()->execute ();
        }
    };
    repository.adopt ((Add_model_dialog*) new Qt_add_model_dialog());

    repository.adopt ((Open*)           new Qt_open());
    repository.adopt ((Add*)            new Qt_add());
    repository.adopt ((Pull_on*)        new Qt_pull_on());

    class Qt_Synchonize_folders : public Synchonize_folders
    {
        void execute (bool on) {Current_folder::singleton().synchonize (on);}
        Command_1 <bool> *  clone () const  {return new Qt_Synchonize_folders;}
    };
    repository.adopt ((Synchonize_folders*)new Qt_Synchonize_folders());

    repository.adopt ((Save_as*)        new Qt_save_as ());
    repository.adopt ((Save*)           new Qt_save    ());
    repository.adopt ((Save_all*)       new Qt_save_all());

    class Qt_exit : public Exit 
    {
        void        execute() {qApp->quit();}
        Command *   clone   () const  {return new Qt_exit;}
    };
    repository.adopt ((Exit*)           new Qt_exit());

    struct Qt_contents : public Contents 
    {
        void  execute() 
        {
            Text command;
            command += Path::doc();
            command += "Documents.html";
            
            QString   str (command.c_str());
            QFileInfo file(str);
            QUrl      url = QUrl::fromLocalFile (file.absoluteFilePath());
            QDesktopServices::openUrl (url);
        }
        Command *   clone   () const  {return new Qt_contents;}
    };
    repository.adopt ((Contents*)       new Qt_contents());

    struct Qt_discuss : public Discuss 
    {
        void  execute() 
        {
            QDesktopServices::openUrl 
            (QString("http://www.agilemolecule.com/forum/"));
        }
        Command *   clone   () const  {return new Qt_discuss;}
    };
    repository.adopt ((Discuss*)       new Qt_discuss());

    class Qt_select : public Select
    {
        void execute () {Panel_select::singleton()->popup ();}
        Command *  clone () const  {return new Qt_select;}
    };
    repository.adopt ((Select*)         new Qt_select  ());


    
    repository.adopt ((Component*)      new Default_component());
    /*repository.adopt ((Bond*)           new Default_bond());
    repository.adopt ((Molecule*)       new Molecule_impl());

    repository.adopt ((Model*)          new Model_impl());
    repository.adopt ((Model_manager*)  new Model_manager_impl());///*/

    class Qt_show_protocol : public Show_protocol
    {
        void        execute ()        
        {
            Panel_protocol::singleton()->popup ();
        }
        Command *   clone   () const  {return new Qt_show_protocol;}
    };
    repository.adopt ((Show_protocol*)  new Qt_show_protocol);

    class Qt_show_monitor : public Show_monitor
    {
        //void        execute ()        {Panel_monitors::singleton()->popup ();}
        void        execute ()        {Panel_monitors::singleton()->popup ();}
        Command *   clone   () const  {return new Qt_show_monitor;}
    };
    repository.adopt ((Show_monitor*)  new Qt_show_monitor);

    class Qt_show_information : public Show_information
    {
        void        execute ()        
        {
            //Form_information::pop_up ();
            Text result;
            Information::singleton().model (result);
            to_user().info (result);
        }
        Command *   clone   () const  {return new Qt_show_information;}
    };
    repository.adopt ((Show_information*)  new Qt_show_information);

    class Qt_show_geometry : public Show_geometry
    {
        void        execute ()  {Panel_geometry::singleton()->popup ();}
        Command *   clone   () const  {return new Qt_show_geometry;}
    };
    repository.adopt ((Show_geometry*)  new Qt_show_geometry);

    class Qt_show_model_movement : public Show_model_movement
    {
        void        execute ()  {Panel_move_model::singleton()->popup ();}
        Command *   clone   () const  {return new Qt_show_model_movement;}
    };
    repository.adopt ((Show_model_movement*)  new Qt_show_model_movement);

    class Set_Z_viewpoint_impl : public Set_Z_viewpoint
    {
        void        execute ()        
        {
            Project::singleton ().current_model().kit().visual().flush_camera();
            
            
            Model_RM_window * window = dynamic_cast <Model_RM_window *>
                (Main_window::singleton ()->current_model_window());

            if (window == 0)
                return;

            Model_RM_widget * widget = window->current_model_widget ();

            //Model_RM_widget * widget = dynamic_cast <Model_RM_widget *>
            //    (window->focusWidget ());

            if (widget == 0)
                FLAW ("Wrong widget");                                      //fix
            
            widget->flush_camera();
        }
        Command *   clone   () const  {return new Set_Z_viewpoint_impl;}
    };
    repository.adopt ((Set_Z_viewpoint*)  new Set_Z_viewpoint_impl);

    class Qt_About : public About
    {
        void        execute () {Panel_about::singleton()->exec ();}
        Command *   clone   () const  {return new Qt_About;}
    };
    repository.adopt ((About*)  new Qt_About);

}

}//MM

