// world.H: complete xrml world class

#ifndef _XRML_WORLD_H_
#define _XRML_WORLD_H_

#include "xrml.H"
#include "Proto.H"

namespace xrml {

// complete XRML world, includes besides the scene graph also the 
// current time, renderer, event queue, bindable node stacks ...
class world {
public:
  //////////////////////////////////////////////////////////
  // 1) Importing a scene graph:

  // Parses open file. Returns scene graph or null if error.
  // 'importer' is a pointer to an object of a children class of
  // importer (see importer.H) and can be used to read
  // alternative file formats. If 'importer' is null, an object of
  // the class vrml2_utf8_importer is used, which parses VRML V2.0
  // utf8 like files.
  MFNode* parse(class file *file, const double start_time, class importer* importer =0);

  // Opens the named file or url and calls the above. If filename
  // is null (e.g. calling parse() without arguments, input
  // is read from stdin.
  MFNode* parse(const char* filename =0, const double start_time=0., class importer* importer =0);

  //////////////////////////////////////////////////////////
  // 2) Rendering

  // Installs a renderer (see renderer.H). Returns previous renderer.
  class renderer* set_renderer(class renderer*);

  // Sets the current time
  void set_time(const double time);
  // Prepares for rendering a new frame, dispatches queued events
  void newframe(void);
  // Renders a frame, generates initial events for next frame
  void render(void);
  // short-cuts:
  inline void newframe(const double t) { set_time(t); newframe(); }
  inline void rendernewframe(const double t) { set_time(t); newframe(); render(); }

  //////////////////////////////////////////////////////////
  // 3) Exporting a scene graph

  // Saves the world 'this' in the file described by the file handle
  // 'file_handle'. The format is determined by 'exporter', which is
  // a pointer to an object of a child class of exporter (exporter.H).
  // If no exporter is given explicitly, the vrml2_utf8_exporter class 
  // is used. The scene graph is then saved in a VRML V2.0 utf8 like file,
  // which can be read by the default importer.
  void save(class file* file_handle, class exporter* exporter =0);

  // Same, but saves to the named file, or to stdout if 
  // 'filename' is null (e.g. when calling save() without arguments)
  void save(const char* filename =0, class exporter* exporter =0);

  //////////////////////////////////////////////////////////
  // Things you will probably never need:

protected:
  bool inited;                  // initialised or not
  char *strpool;		// string pool

  class EventManager* event_m;	// event manager. Maintains event queue.

public:
  PoolDecl(world, "world")

  class file *file;	// file from which the world was read
  char *filename;		// brief descriptive input file name
  double time;			// current time, use set_time() to change it.

  MFNode* sceneGraph;		// scene graph (0 if parse() failed)
  namedNodeTable namedNodes;    // DEF'd nodes
  protoTable protos;            // PROTO's and EXTERNPROTO's

  // Current renderer, set by set_renderer(), used by render().
  class renderer *renderer;

  // Bindable node stacks: one stack for each kind of bindable.
  // The current bindable (e.g. Viewpoint) is on top.
  class StackManager *stacks;

  world();
  void init(const double time =0.);	// various internal initialisations.

  // Queues primary events and dispatches cascade events. Primary
  // events are events generated while parsing or while rendering.
  // They are dispatched in newframe(). Cascade events are events
  // generating while processing primary or other cascade events. They
  // are not queued, but dispatched immediately.
  void postEvent(const class SFNode *srcnode, const class interfaceMember* event) const;

  friend ostream& operator<<(ostream& s, const world* w);

  // Importer/Renderer aids:
  // Fetches and opens urls relative to world url if base_url is not given.
  class file *openFileFromURLs(const MFString& urls, const char*base_url =0) const;

  // makes 'this' the current world. All subsequently created nodes will be
  // registered in this world (by the SFNode constructor).
  class world* make_current(void);

  // adds the node with given name to the named nodes table. Returns
  // index of the new named node in the table.
  int addNamedNode(const char *nameId, SFNode* node);
  // adds the prototye to the table of prototypes
  int addProto(class Proto* proto);
  // looks up a named node/proto, returns null pointer if not found
  class SFNode* lookupNamedNode(const char* nameId) const;
  class Proto* lookupProto(const char* typeId) const;
};

}  // namespace xrml

#endif /*_XRML_WORLD_H_*/
