#ifndef _V4SCENEGRAPH_H
#define _V4SCENEGRAPH_H

#include "safe_include.h" 
#include <gpac/m4_author.h>
#include <gpac/m4_render.h>
#include <gpac/intern/m4_esm_dev.h> // MPEG4CLIENT


#include <wx/gdicmn.h>


#define DICTNAME "__V4dictionnary"


#define FPS 25


class V4StudioFrame;
class V4Service;

extern "C" {
  SFNode *CloneNodeForEditing(LPSCENEGRAPH inScene, SFNode *orig);
  int GetNextNodeID(LPSCENEGRAPH sg);
}

class V4SceneGraph {
public:
	// Constructor / Desctructor
	V4SceneGraph(V4StudioFrame *parent);
	~V4SceneGraph();


	/* file management functions */

	void SaveFile(const char * path);
	void LoadNew(); 
	void LoadFile(const char *path); 
	void LoadFileOld(const char *path); 


	/* Node management functions */

	SFNode *NewNode(u32 tag);
	SFNode *CopyNode(SFNode *node, SFNode *parent, bool copy);
	SFNode *SetTopNode(u32 tag);  // TODO : will destroy dictionnary


	/* Dictionnary functions */

	// adds a node to the dictionnary, increases its reference count, the node must already have an ID
	void AddToDictionnary(SFNode * node);

	// removes a node from the dictionnary = DELETES it's ID
	void RemoveFromDictionnary(SFNode * node);

	SFNode * GetDictionnary() const;


	/* Various */

	void LoadCommand(u32 commandNumber); // ?
	M4StreamContext * GetBifsStream();   // Get the first stream with id = 3


	/* access to private members */

	// SceneSize
	void SetSceneSize(int w, int h);
	void GetSceneSize(wxSize &size);

	// Renderer (owned by the terminal)
	void SetRenderer(LPSCENERENDER sr) { m_pSr = sr; }
	LPSCENERENDER GetSceneRenderer() { return m_pSr; }

	// InlineScene
	// TODO : Should be modified ?
	LPINLINESCENE GetInlineScene() { return m_pIs; }

	// SceneManager
	// TODO : Should be modified ?
	M4SceneManager * GetSceneManager() { return m_pSm; }

	// SceneGraph
	LPSCENEGRAPH GetSceneGraph() { return m_pSg; }
	SFNode *GetRootNode() { return SG_GetRootNode(m_pSg); }

	// TODO : terminal
	private:

	/* dictionnary function */

	// initializes the dictionnary node
	void CreateDictionnary();

	// Finds all node with an ID from the given node and adds them to the node pool and the dictionnary
	void AddRecursive(SFNode * node, bool parentAdded = false);

	// calls a proper function to add the node according to its type
	void AddEffective(SFNode * node);

	// Create a dummy node of type tag and it to the specified field (or reimplace if the field is single valued)
	SFNode * CreateDummyNode(const u32 tag, SFNode * parent, const u32 fieldIndex);

	// Sets the first node as a child of the second using the given field
	void MakeChild(SFNode * child, SFNode * parent, const u32 fieldIndex);

	// Checks is specified node as a parent with an ID
	SFNode * V4SceneGraph::HasDefParent(SFNode * node);

	// adds a node to the dictionnary
	void AddGen(SFNode * node);
	void AddGeometry(SFNode * node);
	void AddAppearance(SFNode * node);
	void AddTexture(SFNode * node);
	void AddMaterial(SFNode * node);


protected:

	// self created
	LPINLINESCENE m_pIs;
	LPSCENEGRAPH  m_pSg;
	M4SceneManager *m_pSm;
	SFNode * dictionnary;

	// from other objects
	LPSCENERENDER m_pSr;
	MPEG4CLIENT m_term;
	V4StudioFrame * frame;
	
	char *m_pOriginal_mp4;
	Bool m_bEncodeNames;
	V4Service *m_pService;
};

#endif

