#include "Test.h"

#include "Molecular_detector.h"
#include "Atom_impl.h"
#include "Element.h"
#include "Default_bond.h"
#include "Molecule_impl.h"
#include "Model.h"
#include "Create.h"
#include "Path.h"
#include "Log.h"

namespace MM
{
class Molecular_iterator;

class Molecular_detector_test : public Test
{
    Molecular_detector *link;
    Molecular_iterator *link2;

public:
    Molecular_detector_test (const Text& suite_name) : Test (suite_name) { }

    void run()
    {
        test_1 ();      count_tests ();
        test_DNA_6 ();  count_tests ();
    }

    void test_1 ()
    {
        Own <Model>     model (prototype <Model> (). clone ());

        Atom_impl *a1=new Atom_impl("C"); a1->set_charge(11); model().add_atom(a1);
        Atom_impl *b1=new Atom_impl("C"); b1->set_charge(12); model().add_atom(b1);
        Atom_impl *a2=new Atom_impl("C"); a2->set_charge(21); model().add_atom(a2);
        Atom_impl *b2=new Atom_impl("C"); b2->set_charge(22); model().add_atom(b2);
        Atom_impl *a3=new Atom_impl("C"); a3->set_charge(31); model().add_atom(a3);
        Atom_impl *b3=new Atom_impl("C"); b3->set_charge(32); model().add_atom(b3);
        Atom_impl *a4=new Atom_impl("C"); a4->set_charge(41); model().add_atom(a4);
        Atom_impl *b4=new Atom_impl("C"); b4->set_charge(42); model().add_atom(b4);
        Atom_impl *a5=new Atom_impl("C"); a5->set_charge(51); model().add_atom(a5);
        Atom_impl *b5=new Atom_impl("C"); b5->set_charge(52); model().add_atom(b5);

        Default_bond *bond1= new Default_bond (*a1, *b1); model().add_bond (bond1);
        Default_bond *bond2= new Default_bond (*a2, *b2); model().add_bond (bond2);
        Default_bond *bond3= new Default_bond (*a3, *b3); model().add_bond (bond3);
        Default_bond *bond4= new Default_bond (*a4, *b4); model().add_bond (bond4);

        Molecule_impl *mol1= new Molecule_impl ();  model().add_molecule (mol1); 
        Molecule_impl *mol2= new Molecule_impl ();  model().add_molecule (mol2); 
        Molecule_impl *mol3= new Molecule_impl ();  model().add_molecule (mol3); 
        Molecule_impl *mol5= new Molecule_impl ();  model().add_molecule (mol5); 

        mol1->add_atom (*a1);   mol1->add_atom (*b1);
                                mol2->add_atom (*b2);
        mol3->add_atom (*a3);
        
        mol5->add_atom (*a5);   mol5->add_atom (*b5);

        mol1->set_mm_type(1);
        mol2->set_mm_type(2);
        mol3->set_mm_type(3);
        mol5->set_mm_type(5);

        TEST ("", model().atom_count()     == 10);
        TEST ("", model().bond_count()     == 4);
        TEST ("", model().molecule_count() == 4);

        Molecular_detector detector (model());
        detector.execute ();

        /*log () << "\n### " << model().molecule_count() << "\n";
        log () << model().molecule(0).atom_count() << " " << model().molecule(0).mm_type() << "\n";
        log () << model().molecule(1).atom_count() << " " << model().molecule(1).mm_type() << "\n";
        log () << model().molecule(2).atom_count() << " " << model().molecule(2).mm_type() << "\n";
        log () << model().molecule(3).atom_count() << " " << model().molecule(3).mm_type() << "\n";
        log () << model().molecule(4).atom_count() << " " << model().molecule(4).mm_type() << "\n";
        log () << model().molecule(5).atom_count() << " " << model().molecule(5).mm_type() << "\n";
        //log () << model().molecule(6).atom_count() << " " << model().molecule(6).mm_type() << "\n";//*/

        TEST ("", model().atom_count()     == 10);
        TEST ("", model().bond_count()     == 4);
        TEST ("", model().molecule_count() == 6);

        TEST ("",  model().molecule (0).atom_count() == 2);
        TEST ("",  model().molecule (0).mm_type() == 1);
        TEST ("", &model().molecule (0).atom(0) == a1);
        TEST ("", &model().molecule (0).atom(1) == b1);

        TEST ("",  model().molecule (1).atom_count() == 2);
        TEST ("",  model().molecule (1).mm_type() == 0);
        TEST ("", &model().molecule (1).atom(0) == a3);
        TEST ("", &model().molecule (1).atom(1) == b3);

        TEST ("",  model().molecule (2).atom_count() == 1);
        TEST ("",  model().molecule (2).mm_type() == 0);
        TEST ("", &model().molecule (2).atom(0) == a5);

        TEST ("",  model().molecule (3).atom_count() == 2);
        TEST ("",  model().molecule (3).mm_type() == 0);
        TEST ("", &model().molecule (3).atom(0) == a2);
        TEST ("", &model().molecule (3).atom(1) == b2);

        TEST ("",  model().molecule (4).atom_count() == 2);
        TEST ("",  model().molecule (4).mm_type() == 0);
        TEST ("", &model().molecule (4).atom(0) == a4);
        TEST ("", &model().molecule (4).atom(1) == b4);

        TEST ("",  model().molecule (5).atom_count() == 1);
        TEST ("",  model().molecule (5).mm_type() == 0);
        TEST ("", &model().molecule (5).atom(0) == b5);
    }

    void test_DNA_6 ()
    {
        Own <Model>     model (prototype <Model> (). clone ());
        model(). load (Path::tests() + "B_DNA_6.hin");

        TEST ("", model().molecule_count() == 2);
        
        model().molecule (0).set_mm_type (1);
        model().molecule (1).set_mm_type (2);

        Molecular_detector detector (model());
        detector.execute ();

        TEST ("", model().molecule_count() == 2);
        TEST ("", model().molecule (0).mm_type() == 1);
        TEST ("", model().molecule (1).mm_type() == 2);
    }
};

Molecular_detector_test test_molecular_detector ("correctness");

}//MM
