/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Base scene-graph class.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef GRAPH_BASE_SCENE_GRAPH_HH
#define GRAPH_BASE_SCENE_GRAPH_HH 1

#include <set>
#include <map>
#include "object/module.hh"
#include "object/events.hh"
namespace object { class Object; }
using namespace object;
namespace graph { class NodeSort; }

namespace graph {

////////////////////////////////////////////////////////////////////////////////
/// @brief Base scene-graph class.
///
/// See scene_graph.hh.
///
/// Functionality of this base class:
/// - creates and caches "branch nodes" for state-sorting according to NodeSort
/// - can attach low-level nodes
/// - can attach higher-level Objects
/// - automatically detaches Objects when DestroyObject event is broadcast
///
class BaseSceneGraph : public osg::Referenced
{
PREVENT_COPYING(BaseSceneGraph)
//protected:  // else SceneGraph cannot substitute BaseSceneGraph for ShadowSceenGraph
public:
                BaseSceneGraph( RefPtr<GroupNode> rootNode = new GroupNode );
    virtual     ~BaseSceneGraph();

// Public interface:
public:
    virtual RefPtr<GroupNode>   GetRootNode( void ) { return mBaseRootNode.get(); }
    virtual void                AttachNode( RefPtr<Node> node, const NodeSort& nodeSort );
    void                        AttachBranchNode( RefPtr<GroupNode> branchNode );
    virtual void                AttachObject( shptr<Object> object, const NodeSort& nodeSort );
    virtual void                DetachNode( RefPtr<Node> node );
    void                        DetachBranchNode( RefPtr<GroupNode> branchNode );
    virtual void                DetachObject( shptr<Object> object );
    virtual bool                IfNodeAttached( Node& node );
    virtual bool                IfObjectAttached( shptr<Object> object );
    virtual void                Flush( void );

// Private/protected methods:
protected:
    void                        SetRootNode( RefPtr<GroupNode> rootNode );
    void                        SetDefaultState( RefPtr<Node> node );
    void                        AttachNode( RefPtr<Node> node, RefPtr<GroupNode> parent );
    void                        Optimize( RefPtr<Node> node, const NodeSort& nodeSort );
private:
    void                        ArrangeNodes( void );
    CLASS_DESTROY_OBJECT_LISTENER( BaseSceneGraph, mBaseSceneGraph )

// Data members:
private:
    typedef std::map<NodeSort,RefPtr<GroupNode> > NodeSortMap;
    typedef std::set<shptr<Object> > Objects;
    CLASS_VAR NodeSort      msBranchNodeSort;   ///< default branch has default NodeSort
    RefPtr<GroupNode>       mBaseRootNode;      ///< the absolute root node
    RefPtr<GroupNode>       mBranchNode;        ///< group node with default state
    NodeSortMap             mNodeSortMap;       ///< sorts nodes with shared state
    Objects                 mObjects;           ///< AttachObject() implies hold ref to Object
public:
    DECLARE_TYPESIG(TYPESIG_SCENE_GRAPH)  // final member
};

} // namespace graph

#endif // GRAPH_BASE_SCENE_GRAPH_HH
