#ifndef _V4SceneManager_H
#define _V4SceneManager_H

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


#include <wx/gdicmn.h>


#define DICTNAME "__V4dictionnary"


class V4StudioFrame;

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

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

	// reusable nodes, sorted by tag
	V4NodePools pools;

	/* 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

	void CreateIDandAddToPool(SFNode *node);

	/* 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);

  // FrameRate
  void SetFrameRate(const u32 framerate_) { frameRate = framerate_; }
  u32 GetFrameRate() const { return frameRate; }

  // accesses Length
  void SetLength(const u32 length_);
  u32 GetLength() const { return length; }

  // accesses units
  void SetUnits(u32 units_) { units = units_; }
  u32 GetUnits() const { return units; }



	LPSCENERENDER GetSceneRenderer() { return m_gpac_panel->GetSceneRenderer(); }

	// InlineScene
	LPINLINESCENE GetInlineScene() { return m_pIs; }

	// SceneGraph
	LPSCENEGRAPH	GetSceneGraph() { return m_pIs->graph; }
	SFNode			*GetRootNode() { return SG_GetRootNode(m_pIs->graph); }

	wxGPACPanel		*GetGPACPanel() { return m_gpac_panel; }
	V4StudioFrame	*GetV4StudioFrame() { return frame; }

	// 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 * V4SceneManager::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;
	M4SceneManager	*m_pSm;
	SFNode			*dictionnary;
	wxGPACPanel		*m_gpac_panel;

	// from other objects
	V4StudioFrame	*frame;

  u8  frameRate;
  u32 length;            // in frames!
  u32 units;             // = 1000
	
};

#endif

