#include "Test.h"

#include "Model.h"
#include "Atom_impl.h"
#include "Hyperchem_attributes.h"
#include "Pdb_attributes.h"
#include "ID.h"
#include "Bond.h"

#include <typeinfo>

#if defined WIN32
#pragma warning(disable : 4800)
#endif

namespace MM
{

class Clone_test : public Test
{
public:
    Clone_test( const Text & suite_name ) : Test( suite_name ) { }

    void run()
    {
        test_mm_atom();    count_tests();
    }
    void test_mm_atom();
};

Clone_test test_clone ("correctness");

void Clone_test::
test_mm_atom()
{
    Own <Atom_impl> prototype( new Atom_impl("C") );
    Own <Atom>      clone (prototype().clone());

    TEST("Clone belong to the same element.", 
        clone().element() == "C" );

    TEST("Clone has the same mass.", 
        clone().mass() == prototype().mass() );

    TEST("Clone has not pdb attributes.", 
//        !((Atom_impl&)clone()).kit().has_pdb_attributes() );
        !clone().kit().has_pdb_attributes() );

    TEST("Clone has not hyperchem attributes.", 
//        !((Atom_impl&)clone()).has_hyperchem_attributes() );
        !clone().kit().has_hyperchem_attributes() );


    TEST( Text() + "Clone (" + typeid( clone() ).name() +
        ") belong to the same class as prototype ("
        + typeid( prototype() ).name() + ").", 

        typeid (clone()) == typeid (prototype()));

    //===========================================================
    
    Atom_impl & clone1 = dynamic_cast <Atom_impl&> (clone());

    clone1.set_element( "Mn" );
    clone1.set_x( 1 );
    clone1.set_y( 2 );
    clone1.set_z( 3 );

    Pdb_attributes * pdb_attributes = new Pdb_attributes();
    pdb_attributes->set_name           ( "PDB Name" );
    pdb_attributes->set_residue_name   ( "PDB Residue name" );
    pdb_attributes->set_residue_number ( 321 );
    pdb_attributes->set_chain_id       ( 111 );
    pdb_attributes->set_number         ( 123 );
    clone1.kit().add_pdb_attributes( pdb_attributes );

    Hyperchem_attributes * hyperchem_attributes 
        = new Hyperchem_attributes (clone1);
    hyperchem_attributes->set_number   ( 555 );
    hyperchem_attributes->set_name     ( "HH name"  );
    hyperchem_attributes->set_type     ( "HH type"  );
    hyperchem_attributes->set_flags    ( "HH flags" );
    clone1.kit().add_hyperchem_attributes( hyperchem_attributes );

    Own <Atom_impl>  clone2( dynamic_cast<Atom_impl*>( clone().clone() ));
    
//    TEST("", !  clone2().id().is_equal( clone1.id() ));
    TEST("", ! (clone2().id() == clone1.id()) );
    TEST("",    clone2().id() != clone1.id() );

    TEST("", clone2().element() == "Mn" && clone2().element() != "C" );
    TEST("", clone2().x() == 1 && clone2().y() == 2 && clone2().z() == 3 );

    TEST("Clone has pdb attributes",       clone2().kit().has_pdb_attributes() );
    TEST("Clone has hyperchem attributes", clone2().kit().has_hyperchem_attributes() );

    TEST("", clone2().kit().pdb().name()           == "PDB Name" );
    TEST("", clone2().kit().pdb().residue_name()   == "PDB Residue name" );
    TEST("", clone2().kit().pdb().residue_number() == 321 );
    TEST("", clone2().kit().pdb().chain_id()       == 111 );
    TEST("", clone2().kit().pdb().number()         == 123 );

    TEST("", clone2().kit().hyperchem().number()   == 555 );
    TEST("", clone2().kit().hyperchem().name()     == "HH name" );
    TEST("", clone2().kit().hyperchem().type()     == "HH type" );
    TEST("", clone2().kit().hyperchem().flags()    == "HH flags" );
}

}//MM
