#ifndef GCOBJECT_H
#define GCOBJECT_H

class GcObject;

class GcOpaqueObjectList
{
public:
  const char* gol_name;
  const char* gol_prefix;

  GcObject* gol_first;
  unsigned int gol_items;

  //mex_mt_object_t gol_mex_lst;

  unsigned int objAdd_(GcObject& obj);

  void registerList();

  GcOpaqueObjectList* gol_next_lst;
};

template<class T_> class GcObjectList: public GcOpaqueObjectList
{
public:
  GcObjectList(const char* name, const char* unnamed_prefix=0)
  {
    gol_name=name;
    gol_prefix=unnamed_prefix ? unnamed_prefix : name;
    gol_first=0;
    gol_items=0;
    registerList();
  }

  void add(T_& obj) { GcOpaqueObjectList::objAdd_(obj);}
};

//struct mex_mt_tag_t;
#define GC_OBJ_MON_DECLARE(class_name_)\
  friend class GcObjMonFriend_##class_name_;\
  static const int class_name_##_cookie_;\
  virtual const void* mexMetatype() const { return &class_name_##_cookie_;}
 /*virtual void gc_obj_mon_metaregister() const { extern void gc_obj_mon_metaregister(const class_name_*); gc_obj_mon_metaregister(this);}*/

#define GC_OBJ_MON_DEFINE(class_name_) const int class_name_::class_name_##_cookie_=0;

class GcObject
{
public:
  GcObject(GcObject* parent=0, const char* name=0, GcOpaqueObjectList* lst=0);
  virtual ~GcObject();

  const char* objName() const;
  void setObjName(const char* name);

  GcObject* next() const { return gco_next_;}

  GC_OBJ_MON_DECLARE(GcObject)
protected:
  void setParent(GcObject* parent);

  GcOpaqueObjectList* gco_list_;
  GcObject* gco_parent_;
  GcObject* gco_next_;
  GcObject* gco_children_;

private:
  unsigned int gco_instance_num_;
public:
  char* gco_name_ptr_;
  char gco_name_[32];

  friend class GcObjectServices;
  friend class GcOpaqueObjectList;

private:

  GcObject(const GcObject&);
  void operator=(const GcObject&);
};


#endif // GCOBJECT_H
