#ifndef __H_OBJECT__
#define __H_OBJECT__

#include "defs.h"

/** @file
 * Object is the base object for many of the objects that are used in the game.
 * It has some primitives that make it easy to use with the EcmaScript
 * interpretor.
 *
 * It is also the base for the GameObject class.
 *
 * @warning Note that there is no type-checking. So be careful when using this.
 *          You will have to keep track of what objects inherent from which
 *          object. Also note that there is no consent of interfaces.
 */

BEGIN_DECLS


#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct Object Object;
typedef struct ObjectClass ObjectClass;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

/**
 * Is the primitive for the the <tt>ObjectClass::to_string_func</tt> method in
 * the <tt>ObjectClass</tt>.
 */
typedef char * (* ToStringFunc)(Object * object);

/**
 * This is the primitive for the <tt>ObjectClass::new_func</tt> method.
 */
typedef char * (* NewFunc)(Object * object, ...);

/**
 * The class for the Object, it is what holds the methods for the object.
 */
typedef struct ObjectClass {
  NewFunc new_func;
  FreeFunc free_func;
  ToStringFunc to_string_func;
} ObjectClass;

typedef struct Object {
  ObjectClass * klass;
  char * name;
  
  /* Some reserved space in the Object instance, for good measure. These should
   * be NULL
   */
  _pointer reserved0;
  _pointer reserved1;
  
  _pointer priv;
} Object;


/**
 * Initialises the Object to a sane values.
 * 
 * @warning This does NOT allocate any memory for the instance.
 * 
 * @param object The object to initialise.
 * 
 * @param name The name of the object instance, this should be the same as the
 *             "class" name. IE: If the instance is of the type "Foo", then the
 *             name should be the same.
 * 
 * @param klass The class instance to be added to the object instance.
 */
void object_initialize (Object * object,
                        char * name,
                        _pointer klass);

/**
 * Initialises a ObjectClass with methods.
 *
 * @warning This does NOT allocate any memory for the ObjectClass.
 *
 * @param klass The ObjectClass to initialise.
 * 
 * @param new_func The method that is used when creating a new instance of
 *                 the object that the class belongs to.
 *
 * @param to_string_func The method to be used when calling
 *        <tt>object_to_string ()</tt> on the object.
 */
void object_class_initialize (ObjectClass * klass,
                              NewFunc new_func,
                              FreeFunc free_func,
                              ToStringFunc to_string_func);

/**
 * Add a private data structure ta a Object.
 *
 * @param object the object to add the private data to.
 * @param priv_data the data structure to add to the object.
 */
void object_add_private (Object * object, _pointer priv_data);

/**
 * Create a new object of the same type as the one that this is executed on.
 *
 * This is does not copy the data in the object, it only crates a new instance
 * of the object. This is generally not helpful.
 */
Object * object_new_from_object (Object * self);

/**
 * Creates a null-terminated string that can be used with in different ways, be
 * it for debugging or other purposes.
 */
char * object_to_string (Object * object);

/**
 * Frees an object.
 * 
 * This will call an objects free method.
 *
 * @warning This will only work on objects that inherent from the Object. It
 *          may or will cause undefined behaviour when used with object that do
 *          not inherent from Object.
 */
void object_free (Object * object);

END_DECLS

#endif /* __H_OBJECT__ */
