/* 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_RESOURCE
#define OSGCOMPUTE_RESOURCE 1

#include <vector>
#include <set>
#include <map>
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <osgCompute/Export>
#include <osgCompute/Callback>

namespace osgCompute
{
    typedef std::set< std::string >                                           	IdentifierSet;
    typedef std::set< std::string >::iterator                                 	IdentifierSetItr;
    typedef std::set< std::string >::const_iterator                           	IdentifierSetCnstItr;

    typedef std::vector< osg::ref_ptr<Resource> >                              	ResourceList;
    typedef std::vector< osg::ref_ptr<Resource> >::iterator                    	ResourceListItr;
    typedef std::vector< osg::ref_ptr<Resource> >::const_iterator              	ResourceListCnstItr;

    typedef std::set< osg::ref_ptr<Resource> >                                  ResourceSet;
    typedef std::set< osg::ref_ptr<Resource> >::iterator                        ResourceSetItr;
    typedef std::set< osg::ref_ptr<Resource> >::const_iterator                  ResourceSetCnstItr;

	//! Base class for resources 
    /** 
		Abstract base class for device dependent objects.
		Any object that is in any way connected with a device 
		context should derive from osgCompute::Resource, 
		like Memory or Module objects. Resources have 
		string identifiers to uniquely distinguish between 
		different resources of the same type.
		\code
		osg::ref_ptr<osgCompute::Resource> resourceA = new osgCuda::Buffer;
		resourceA->addIdentifier("INPUT RESOURCE");
		osg::ref_ptr<osgCompute::Resource> resourceB = new osgCuda::Buffer;
		resourceA->addIdentifier("OUTPUT RESOURCE");
		\endcode
		Each module will check for these names during acceptResource() 
		in order to identify its resources of interest.
    */
    class LIBRARY_EXPORT Resource : public osg::Object
    {
    public:
		/** Constructor. Identifier list is empty by default.
		*/
        Resource();

		/** Init will check for internal parameters applied to 
		resources and will create device dependent objects.
		@return Returns true if initialization was successful
		*/
        virtual bool init();

		/** Adds a identifier to the resource
		@param[in] identifier new string identifier of the resource.
		*/
        virtual void addIdentifier( const std::string& identifier );
        
		/** Removes identifier from the resource
		@param[in] identifier string identifier to remove.
		*/
		virtual void removeIdentifier( const std::string& identifier );
        
		/** Returns true if the resource is identified by identifier.
		@return Returns true if identifier is found. Returns false if 
		it is not.
		*/
		virtual bool isIdentifiedBy( const std::string& identifier ) const;
    		
		/** Add unique identifiers to the resource.
		@param[in] identifiers List of identifiers.
		*/    
		virtual void setIdentifiers( IdentifierSet& identifiers );
        
		/** Returns all identifiers of the resource.
		@return Returns a reference to the list with all identifiers.
		*/ 	
		virtual IdentifierSet& getIdentifiers();

		/** Returns all identifiers of the resource.
		@return Returns a reference to the list with all identifiers.
		*/ 	
        virtual const IdentifierSet& getIdentifiers() const;

		/** Returns wether the resource is initialized or not.
		@return Returns true if resource is not initilalized 
		*/
        virtual bool isClear() const;

		/** Clear resource and release all device objects.
		After calling this method isClear() will return true 
		and init() should be called before using this resource.
		*/
        virtual void clear();

        /** Release all device objects associated with this resource. 
		Is called by clear().
        */
        virtual void releaseObjects();

    protected:
		/** Destructor. Will call clearLocal() first.
		*/
        virtual ~Resource();

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

		void clearLocal();

		IdentifierSet                       _identifiers;
		bool                                _clear;

    };
}

#endif //OSGCOMPUTE_RESOURCE
