/* osgCompute - Copyright (C) 2008-2009 SVT Group
 *                                                                     
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *                                                                     
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesse General Public License for more details.
 *
 * The full license is in LICENSE file included with this distribution.
*/

#ifndef OSGCOMPUTE_COMPUTATIONBIN
#define OSGCOMPUTE_COMPUTATIONBIN 1

#include <osg/ref_ptr>
#include <osg/Object>
#include <osg/NodeVisitor>
#include <osgUtil/RenderBin>
#include "osgCompute/Export"
#include "osgCompute/Callback"
#include "osgCompute/Module"

namespace osgCompute
{
    class Computation;

    typedef std::multimap< std::string, osg::ref_ptr<osgCompute::Param> >                         HandleToParamMap;
    typedef std::multimap< std::string, osg::ref_ptr<osgCompute::Param> >::iterator               HandleToParamMapItr;
    typedef std::multimap< std::string, osg::ref_ptr<osgCompute::Param> >::const_iterator         HandleToParamMapCnstItr;

    /**
    mist
    */
    class LIBRARY_EXPORT ComputationBin : public osgUtil::RenderBin 
    {
    public:
        ComputationBin(); 
        ComputationBin(osgUtil::RenderBin::SortMode mode);

        META_Object( osgCompute, ComputationBin )
        
        virtual bool init( Computation& computation );
        virtual void reset();

        virtual void drawImplementation( osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous );
        virtual unsigned int computeNumberOfDynamicRenderLeaves() const;

        virtual bool hasModule( const std::string& moduleName ) const;
        virtual bool hasModule( Module& module ) const;
        virtual bool hasModules() const;
        virtual Module* getModule( const std::string& moduleName );
        virtual const Module* getModule( const std::string& moduleName ) const;
        virtual ModuleList* getModules();
        virtual const ModuleList* getModules() const;
        virtual unsigned int getNumModules() const;

        inline void setContext( Context& context );
        inline Context* getContext();
        inline const Context* getContext() const;
        inline bool isDirty() const;
        inline Computation* getComputation();
        inline const Computation* getComputation() const;
        inline LaunchCallback* getLaunchCallback();
        inline const LaunchCallback* getLaunchCallback() const;

        virtual void clear();

    protected:
        friend class Computation;
        virtual ~ComputationBin() { clearLocal(); }
        void clearLocal();


        virtual void launch() const;

        // members
        Computation*                         _computation;  
        bool                                 _dirty;
        LaunchCallback*                      _launchCallback;
        ModuleList                           _modules;
        HandleToParamMap                     _paramHandles; 
        mutable osg::ref_ptr<Context>        _context;               

    private:
        // copy constructor and operator should not be called
        ComputationBin(const ComputationBin&, const osg::CopyOp& ) {}
        inline ComputationBin &operator=(const ComputationBin &) { return *this; }
    };

    /////////////////////////////////////////////////////////////////////////////////////////////////
    // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////////////
    //------------------------------------------------------------------------------
    inline bool ComputationBin::isDirty() const
    { 
        return _dirty; 
    }

    //------------------------------------------------------------------------------
    inline Computation* ComputationBin::getComputation()
    { 
        return _computation; 
    }

    //------------------------------------------------------------------------------
    inline const Computation* ComputationBin::getComputation() const
    { 
        return _computation; 
    }

    //------------------------------------------------------------------------------
    inline LaunchCallback* ComputationBin::getLaunchCallback()
    { 
        return _launchCallback; 
    }

    //------------------------------------------------------------------------------
    inline const LaunchCallback* ComputationBin::getLaunchCallback() const
    { 
        return _launchCallback; 
    }

    //------------------------------------------------------------------------------
    inline void ComputationBin::setContext( Context& context )
    {
        _context = &context;
    }

    //------------------------------------------------------------------------------
    inline Context* ComputationBin::getContext()
    {
        return _context.get();
    }

    //------------------------------------------------------------------------------
    inline const Context* ComputationBin::getContext() const
    {
        return _context.get();
    }
}

#endif //OSGCOMPUTE_COMPUTATIONBIN
