namespace boost { namespace python
{
template<class FC_PTR_TYPE>
struct pointee< OSG::RefPtr< FC_PTR_TYPE > >
{
   typedef typename FC_PTR_TYPE::StoredObjectType type;
};

template<class FC_PTR_TYPE>
inline typename OSG::RefPtr<FC_PTR_TYPE>::StoredObjectType*
   get_pointer(OSG::RefPtr< FC_PTR_TYPE > const& p)
{
   return p.get().getCPtr();
}
}}


namespace pyopensg
{

/** For a given Ptr type, create an object with the refptr type, and return that object. */
template <class RefPtrType>
struct fcptr_to_python
{
   static PyObject *convert(typename RefPtrType::FCPtrType const& fcPtr)
   {
      return bp::incref(bp::object(RefPtrType(fcPtr)).ptr());
   }
};

template <class RefPtrType>
struct register_fcptr_to_python
{
   static void execute()
   {
      bp::to_python_converter<typename RefPtrType::FCPtrType, fcptr_to_python<RefPtrType> >();
   }
};

// Template class to register from_python converter for fcptr types.
//   This is needed atleast for conversion from None.
//
// Base on shared_ptr_from_python in converter/shared_ptr_from_python.hpp
template<typename FCPtrType>
struct fcptr_from_python
{
   typedef typename FCPtrType::StoredObjectType Pointee;   // The type we point to

   fcptr_from_python()
   {
      bp::converter::registry::insert(&convertible, &construct, bp::type_id<FCPtrType>());
   }

private:

   static void* convertible(PyObject* p)
   {
      // Always produce a pointer from none
      if (Py_None == p)
      { return p; }
      else
      { return NULL; }
   }

   static void construct(PyObject* source,
                         bp::converter::rvalue_from_python_stage1_data* data)
   {
     void* const storage
        = ((bp::converter::rvalue_from_python_storage<FCPtrType>*)data)->storage.bytes;

     // Deal with the "None" case.
     if (data->convertible == source)
     {
        new (storage) FCPtrType();
     }
     else
     {
        // Shouldn't ever happen.  We can't convert like this from openSG
        // new (storage) FCPtrType(static_cast<Pointee*>(data->convertible));
        assert(false && "Tried to convert a raw OpenSG fc * to a fc_ptr type.");
        new (storage) FCPtrType();
     }

     data->convertible = storage;
   }

};


// Compare and has two RefPtrs
template <class RefPtrType>
static int cmp_ref_ptrs(const RefPtrType& left, const RefPtrType& right)
{
   //          10   - 20  = -10
   int diff = int(left.get().getFieldContainerId())-int(right.get().getFieldContainerId());
   return diff;
}

template <class RefPtrType>
static int hash_ref_ptr(const RefPtrType& ref)
{
   return ref.get().getFieldContainerId();
}

}
//@}
