// Author: Juan Carlos De Abreu (jcabreur@gmail.com)
//
// This file define a singleton class that control and manage the scene.
//
// The first thing to call is the loadSetting() and then load() methods, only
// after call these methods it can start to call the render method.
//
// Once the app finish must be call the method release(), otherwise will be 
// memory leaks.

#ifndef SCENE_SCENE_H__
#define SCENE_SCENE_H__

#include "../global.h"
#include "../math/Vector.h"
#include "../Base/Singleton.h"
#include "../Base/Memory/SmartPointer.h"
#include "../Base/Memory/MMObject.h"
#include "scene_nodes.h"
#include "../Camera/Camera.h"

BEGIN_TEG_NAMESPACE();

// Macro to load a scene.
#define LOAD_SCENE() Scene::GetInstance().Load()

// Macro to access the info in the scene.
#define SCENE_MODEL(i) Scene::GetInstance().models[i]

class Scene : public Singleton<Scene> {
 public:
  // Scene constructor and destructor.
  Scene();
  ~Scene();

  // Accessor and mutator methods to Scene attributes.
  const SmartPointer<Camera>& camera() const;
  SmartPointer<ISceneNode>& root();
  void set_camera(const SmartPointer<Camera>& camera);
  void set_root(const SmartPointer<ISceneNode>& root);

  // Methods to add a light and to add a geometry to the scene.
  void AddSceneLight(const SmartPointer<LightNode>& light_node);
  void AddSceneGeometry(const SmartPointer<GeometryNode>& geometry_node);
  
  // Method to display the scene description.
  void Render();
	
  // Methods to load the settings, initial scene description and for release
  // the resources used by the scene.
  void LoadSettings(const std::tstring& path);
  void Load();
  void Release();

 private:
  // Scene atributes, scene node root and camera active in the scene.
  SmartPointer<ISceneNode> root_;
  SmartPointer<Camera> camera_;

  // Flags to know if the scene will be render with shadows and if will be 
  // render with blending.
  bool scene_cast_shadows_;
  bool scene_blend_;

  // Path of the file with the initial description of the scene.
  std::tstring path_name_;

  // Containers to store the geometries and lights that are active in the
  // scene.
  std::vector< SmartPointer<GeometryNode> > scene_geometries_;
  std::vector< SmartPointer<LightNode> > scene_lights_;

  DISALLOW_COPY_AND_ASSIGN(Scene);
};

END_TEG_NAMESPACE();

#endif  // SCENE_SCENE_H__
