//
// This file is part of MolMeccano, a cross-platform C++ chemical library.
//
// Copyright (C) 2001-2007 Alexey Nikitin
//
#include "Model_file.h"

#include "Create.h"
#include "Model.h"
#include "Atom.h"
#include "Bond.h"
#include "Order.h"
#include "Molecule.h"
#include "Model_kit.h"
#include "Array.h"
/*
namespace
{
using namespace MM;

Array <Model_file*> & 
file_type_list ()
{
    static Array <Model_file*> singleton;
    return singleton;
}

void register_file_type (Model_file &file_type)
{
    file_type_list().push_back (&file_type);
}

}//namespace  //*/


namespace MM
{
// static {

Model_file const & Model_file::
prototype (Text const & file_type)
{
    int size = type_list().size();
    for (int i=0;  i<size;  ++i)
    {
        Text const & current_type = type_list()[i]->type_name();

        if (current_type == file_type)
            return *type_list()[i];
    }

    Text message;
    message += "No file type '";
    message += file_type;
    message += "'.";
    FLAW (message);
}

int Model_file::
prototype_count ()
{
    return type_list ().size();
}

Model_file const & Model_file::
prototype (int n)
{
    CONTRACT REQUIRE ("", n < prototype_count ());
    return *type_list()[n];
}

Array <Model_file*> & Model_file::
type_list ()
{
    static Array <Model_file*> singleton;
    return singleton;
}

void Model_file::
register_type (Model_file &file_type)
{
    type_list().push_back (&file_type);
}

// } static

Model & Model_file::
model ()
{
    REQUIRE ("Was init", model_ != 0);
    return *model_;
}

Model const & Model_file::
model () const
{
    REQUIRE ("Was init", model_ != 0);
    return *model_;
}

void Model_file::
set_name( const Text & file_name )
{
    Model_kit & kit = model().kit();
	kit.set_file_name (file_name);
}

Text const & Model_file::
name() const 
{ 
    return model().kit().file_name (); 
}

void Model_file::
set_model (Model & model)
{
    model_ = &model;
}

Model_file::
Model_file()
: 
    model_( 0 ), 
    accept_new_fine_types_(Accept_new_fine_types::No),
    accept_new_fine_types_lock_(0)
{
}

Model_file::
Model_file (Model & model)
:
    model_      (&model),
    accept_new_fine_types_(Accept_new_fine_types::No),
    accept_new_fine_types_lock_(0)
{
}

Model_file::
Model_file (Prototype const &)
: 
    model_(0), 
    accept_new_fine_types_(Accept_new_fine_types::No),
    accept_new_fine_types_lock_(0)
{
    register_type (*this);
}

void Model_file::
adopt_builder (Builder * adoptee)
{
    builder_.adopt (adoptee);
}

Builder * Model_file::
orphan_builder ()
{
    return builder_.orphan ();
}

Atom & Model_file::
new_atom( Element element )
{
    //Atom * new_atom = dynamic_cast< Atom* > (prototype <Atom> ().clone());
/*
    //fix dynamic_cast
    Atom * new_atom = dynamic_cast <Atom*> (model().atom_prototype ().clone());
    CHECK("Prototype is MM_atom", new_atom !=0 );
    new_atom->set_element( element );

    return new_atom; //*/

    return builder().new_atom (model(), element);
}

Bond & Model_file::
new_bond (Atom & atom1, Atom & atom2, const Order & order)
{
    //fix to model
    //return prototype <Bond> (). clone (atom1, atom2, order);
    return builder().new_bond (model(), atom1, atom2, order);
}

Distance_restraint & Model_file::
new_distance_restraint (Atom & atom1,
                        Atom & atom2,
                        Text const & type,
                        double       R_eqv,
                        double       K_r)
{
    return builder().new_distance_restraint
        (model(), atom1, atom2, type, R_eqv, K_r);
}

Molecule & Model_file::
new_molecule ()
{
    //fix to model
    //return prototype <Molecule> (). clone();
    return builder().new_molecule (model());
}

Residue  & Model_file::
new_residue ()
{
    return builder().new_residue (model());
}

Joint & Model_file::
new_joint (Atom & stub_atom, Atom & terminal_atom, Atom & directional_atom)
{
    return builder().
        new_joint (model(), stub_atom, terminal_atom, directional_atom);
}

}//MM






