/* -*-c++-*- header - Open Producer - Copyright (C) 2002 Don Burns
 * Distributed under the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL)
 * as published by the Free Software Foundation.
 */
#ifndef OSG_CAMERA_GROUP_H
#define OSG_CAMERA_GROUP_H

#include <Producer/Export>
#include <vector>

#include <Producer/CameraGroup>
#include <osg/Node>
#include <osg/StateSet>
#include <osg/Timer>
#include <osg/FrameStamp>
#include <osg/DisplaySettings>
#include <Producer/osgSceneHandler>

namespace Producer {

class OsgCameraGroup : public Producer::CameraGroup
{
    public :
        OsgCameraGroup() : Producer::CameraGroup() 
        { _init(); }

        OsgCameraGroup(Producer::CameraConfig *cfg) : Producer::CameraGroup(cfg) 
        { _init(); }

        OsgCameraGroup(const std::string& configFile) : Producer::CameraGroup(configFile) 
        { _init(); }

        virtual ~OsgCameraGroup() {}

        void setSceneData( osg::Node *scene ) 
        { 
            _scene_data = scene; 
            if( shvec.size() > 0 )
            {
                std::vector <OsgSceneHandler *>::iterator p;
                for( p = shvec.begin(); p != shvec.end(); p++ )
                {
                    (*p)->setSceneData( _scene_data );
                }
            }
        }
        osg::Node *getSceneData() { return _scene_data; }
        
        
        
        void setDisplaySettings( osg::DisplaySettings *ds ) { _ds = ds; }

        osg::DisplaySettings *getDisplaySettings() { return _ds.get(); }
        
        const osg::DisplaySettings *getDisplaySettings() const { return _ds.get(); }
        
        
        
        void setFrameStamp( osg::FrameStamp* fs )
        {
            _frameStamp = fs;

            for(std::vector <OsgSceneHandler *>::iterator  p = shvec.begin(); p != shvec.end(); p++ )
            {
                (*p)->setFrameStamp( fs );
            }
        }

        osg::FrameStamp *getFrameStamp() { return _frameStamp.get(); }

        const osg::FrameStamp *getFrameStamp() const { return _frameStamp.get(); }


        void setGlobalStateSet( osg::StateSet *sset ) 
        { 
            _global_stateset = sset; 

            for(std::vector <OsgSceneHandler *>::iterator  p = shvec.begin(); p != shvec.end(); p++ )
            {
                (*p)->setGlobalStateSet( _global_stateset );
            }
        }

        void setBackgroundColor( const osg::Vec4& backgroundColor ) 
        {
            _background_color = backgroundColor;

            if( shvec.size() > 0 )
            {
                std::vector <OsgSceneHandler *>::iterator p;
                for( p = shvec.begin(); p != shvec.end(); p++ )
                {
                    (*p)->setBackgroundColor( _background_color );
                }
            }
        }

        void setLODScale( float bias )
        {
            if( shvec.size() > 0 )
            {
                std::vector <OsgSceneHandler *>::iterator p;
                for( p = shvec.begin(); p != shvec.end(); p++ )
                {
                    (*p)->setLODScale( bias );
                }
            }
        }

        void setFusionDistance( osgUtil::SceneView::FusionDistanceMode mode,float value=1.0f)
        {
            if( shvec.size() > 0 )
            {
                std::vector <OsgSceneHandler *>::iterator p;
                for( p = shvec.begin(); p != shvec.end(); p++ )
                {
                    (*p)->setFusionDistance( mode, value );
                }
            }
        }

        osg::Vec4& getBackgroundColor() { return _background_color; }

        const osg::Vec4& getBackgroundColor() const { return _background_color; }

        osg::StateSet *getGlobalStateSet() { return _global_stateset; }

        const osg::StateSet *getGlobalStateSet() const { return _global_stateset; }

        void advance()
        {
            if( !_initialized ) return;
            CameraGroup::advance();        
        }

        bool realize( ThreadingModel thread_model=SingleThreaded )
        {
            if( _initialized ) return false;

            if (!_ds) _ds = osg::DisplaySettings::instance();
            
            _ds->setMaxNumberOfGraphicsContexts( _cfg->getNumberOfCameras() );
            
            for( unsigned int i = 0; i < _cfg->getNumberOfCameras(); i++ )
            {
                Producer::Camera *cam = _cfg->getCamera(i);
                OsgSceneHandler *sh = new OsgSceneHandler(_ds.get());
                sh->setDefaults();
                if( _global_stateset != NULL )
                    sh->setGlobalStateSet( _global_stateset );
                if( _scene_data != NULL )
                    sh->setSceneData( _scene_data );
                sh->setBackgroundColor( _background_color);
                sh->getState()->setContextID(i);
                sh->setFrameStamp( _frameStamp.get() );
                shvec.push_back( sh );

                cam->setSceneHandler( sh );
            }


            /// Make all statesets the same as the first.
            if( _global_stateset == NULL && shvec.size() > 0 )
            {
                std::vector <OsgSceneHandler *>::iterator p;
                p = shvec.begin();
                _global_stateset = (*p)->getGlobalStateSet();
                p++;
                for( ; p != shvec.end(); p++ )
                    (*p)->setGlobalStateSet( _global_stateset );
            }

            CameraGroup::realize( thread_model );        
            _initialized = true;
            return true;
        }

        virtual void frame( )
        {
            CameraGroup::frame();
            _frameStamp->setFrameNumber( _frameStamp->getFrameNumber() + 1 );
        }


    private :
        osg::Node *_scene_data;
        osg::StateSet *_global_stateset;
        osg::Vec4 _background_color;
        std::vector <OsgSceneHandler *>shvec;
        osg::ref_ptr<osg::DisplaySettings>_ds;
        bool _initialized;
        osg::ref_ptr<osg::FrameStamp> _frameStamp;

        void _init()
        {
            _scene_data = NULL;
            _global_stateset = NULL;
            _background_color.set( 0.2f, 0.2f, 0.4f, 1.0f );
            _initialized = false;
            if (!_frameStamp) _frameStamp = new osg::FrameStamp;
        }
};

}

#endif
