#ifndef CREATE_H
#define CREATE_H

#ifndef PROTOTYPE_REPOSITORY_H
#include "Prototype_repository.h"
#endif
    
#ifndef ANY_H
#include "Any.h"
#endif
    
namespace MM
{

// Used as constructors argument.
class Prototype {};
static Prototype  it_is_a_prototype = Prototype (); 

//class None {};
//static None       it_is_none = None (); 


template <typename T> inline T & 
prototype ()
{   
//    return *static_cast <T*> (Prototype_repository::singleton().find (typeid( T )));
    //return *dynamic_cast <T*> (Prototype_repository::singleton().find (typeid( T )));
    //return *any_cast <T> (Prototype_repository::singleton().find (typeid( T )));

    Any & ptr = Prototype_repository::singleton().find (typeid( T* ));
    T* result = any_cast <T*> (ptr);
    return *result;
}

template <typename T> inline T * 
create ()
{
    return prototype <T> (). clone ();
}

template <typename T> inline T * 
create (Text const& type)
{
    Any & ptr = Prototype_repository::singleton().find (type);
    T* result = any_cast <T*> (ptr);
    return result->clone ();
}

template <typename T> inline T & 
singleton ()
{
    //return *static_cast <T*> (Prototype_repository::singleton().find (typeid( T )));
    //return *any_cast <T> (Prototype_repository::singleton().find (typeid( T )));
//    return *any_ptr_cast <T> (Prototype_repository::singleton().find (typeid( T )));

//    typedef typename Loki::TypeTraits <T>::PointeeType  Ptr;
//    typedef typename Loki::TypeTraits <T>::ReferredType Ref;
    Any & ptr = Prototype_repository::singleton().find (typeid( T* ));
    T* result = any_cast <T*> (ptr);
    return *result;
}

template <typename T> inline T & 
nil ()
{
    static T *nil_ptr =0;
    return *nil_ptr;
}


}//MM

#endif //CREATE_H
