/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 * In particular this file is part of the Framework Core Library
 *
 * The iWear Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation as in version 2 of the License.

 *
 * The iWear Framework 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 General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWEAR_MODULEMANAGER_H
#define __IWEAR_MODULEMANAGER_H

#ifndef __IWEAR_MANAGER_H
#include <iwear/manager.h>
#endif

#ifndef __IWEAR_MODULE_ENUMS_H
#include <iwear/module_enums.h>
#endif

#ifndef __IWEAR_PMANBASE_H
#include <iwear/pmanbase.h>
#endif

#ifndef __IWEAR_DEBUGSTREAM_H
#include <iwear/debugstream.h>
#endif



namespace iwear {
/**
 * This is a basic class for all iwear modules. It can offer a bit more than
 * just keeping track of the objects.
 *
 * All other Managers, like the Sensor Manager, Location Manager and so on
 * should be derived from this. There will sooner or later be a
 * GlobalModuleManager which will keep track of all the modules in the system
 * and knows how to pass them to lower levels.
 */
template <class Types, class ObjBase, class MasterObj>
class ModuleManager : public Manager<Types,ObjBase>, virtual public PManBase
{
protected:
    /**
     * This manages the sub managers of the different possible module types...
     */
    map<Types, PManBase* > SubManagers;

    MasterObj* MasterManager;
public:
    MasterObj* get_master_manager( void ) { return MasterManager; }
    ModuleManager( MasterObj* mm, Configuration& cf );
    virtual ~ModuleManager() { SubManagers.clear(); }

    void register_sub_manager( Types st, PManBase * );
   /**
    * @name Powermanagement functions
    *
    * @note This is somewhat tricky. Theoretically this template class can hold
    * arbitraty Elements. But since we need to implement the following three
    * functions this will cause the compiler to bail out, if this will not
    * implement a Module like interface.
    * @{
    */

   /**
    * Put ALL Managed Modules into specified power state.
    * @return Amount of modules put succesfully into the specified power state.
    */
    uint32_t activate_power_state( power_state );

   /**
    * Activate only the Power state of the module with the specifiede uid
    */
    uint32_t activate_power_state( const uid&, power_state );
    uint32_t activate_power_state( Types, power_state );
    /**
     * @}
     */
};

template <class Types, class ObjBase, class MasterObj>
ModuleManager<Types,ObjBase,MasterObj>::ModuleManager( MasterObj* mm, Configuration& cf)
    : 
    Manager<Types,ObjBase>(cf),
MasterManager(mm)
{
//    cout << "CREATING MODULEMANAGER AT " << (void*)this << endl;
}

template <class Types, class ObjBase, class MasterObj>
void ModuleManager<Types,ObjBase,MasterObj>::register_sub_manager( Types st, PManBase * pmb )
{
    d_dbg << demangle_cpp_name(typeid(*this).name()) << i18n::trans(" registered Sub manager ") 
	<< static_cast<void*>( pmb) << i18n::trans(" for type ") << st << std::endl;
    SubManagers[st] = pmb;
}

template <class Types, class ObjBase, class MasterObj>
uint32_t ModuleManager<Types,ObjBase,MasterObj>::activate_power_state( power_state P )
{
    uint32_t cnt = 0;

    typename map<const uid*,ObjBase*, deref_less<const uid*> >::iterator mi (Manager<Types,ObjBase>::IDtoPointer.begin());

    for(; mi != Manager<Types,ObjBase>::IDtoPointer.end(); mi++)
    {
	/// Count only if the return is 0
	cnt += mi->second->activate_power_state( P ) ? 0 : 1;
    }
    return cnt;
}

template <class Types, class ObjBase, class MasterObj>
uint32_t ModuleManager<Types,ObjBase,MasterObj>::activate_power_state( const uid& U, power_state P)
{
    /**
     * 
     */
    typename map<const uid*,ObjBase*, deref_less<const uid*> >::iterator mi (Manager<Types,ObjBase>::IDtoPointer.find(U));
    if ( mi != Manager<Types,ObjBase>::IDtoPointer.end())
    {
	return mi->second->activate_power_state(P);
    }
    return -1;
}

template <class Types, class ObjBase, class MasterObj>
uint32_t ModuleManager<Types,ObjBase,MasterObj>::activate_power_state( Types T, power_state P)
{
    uint32_t cnt = 0;
    typename map<Types, set<ObjBase* > >::iterator mi ( Manager<Types,ObjBase>::TypetoPointer.find(T));
    if ( mi != Manager<Types,ObjBase>::TypetoPointer.end())
    {
	typename set<ObjBase*>::iterator it = mi->second;
	for ( ; it != mi->second.end(); it++ )
	{
	    cnt += it->activate_power_state(P) ? 0 : 1;
	}
    }
    return cnt;
}

} // namespace iwear
#endif

