/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 *
 * 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 __IWPOWER_POWERMANAGER_H
#define __IWPOWER_POWERMANAGER_H

#ifndef __IWEAR_EVENTDISPATCHER_H
#include <iwear/eventdispatcher.h>
#endif

#ifndef __IWEAR_MODULEMANAGER_H
#include <iwear/modulemanager.h>
#endif

#ifndef __IWPOWER_POWER_ENUMS_H
#include <iwpower/power_enums.h>
#endif

#ifndef __IWPOWER_POWER_BASE_H
#include <iwpower/power_base.h>
#endif

#ifndef __IWEAR_FUNCTOR_H
#include <iwear/functor.h>
#endif

#ifndef __IWEAR_TRIPLE_H
#include <iwear/triple.h>
#endif

#ifndef __IWPOWER_POWEREVENT_H
#include <iwpower/powerevent.h>
#endif

#ifndef __IWSENS_SENSORCHECKING_H
#include <iwsens/sensorchecking.h>
#endif

namespace iwear
{
    namespace sensor
    {
class SensorManager;	
	namespace power
	{

class PowerManager : public ModuleManager<powersensor_type,power_base,SensorManager>, public SensorChecking
{
private:
    PowerManager() : ModuleManager<powersensor_type,power_base,SensorManager>(NULL,
	    *((Configuration*)0)) { }
protected:
    virtual void register_external_module( Module* );

    /**
     * Interval in seconds in which we check values
     */
    uint32_t check_interval;

    /**
     * Next check date
     */
    timeval next_check;

    map<pair<const power_base*,eh_capabilities>,pair<int32_t, multimap<int32_t, PowerEvent*> > > SensIntEvMap;

    map<pair<const power_base*,eh_capabilities>,pair<float, multimap<float, PowerEvent*> > > SensFloatEvMap;

    multimap<pair< const power_base*,eh_capabilities>, pair<psunion,PowerEvent*> > SensEvMap;

    void check_all_sensors( EventDispatcher& );

    void check_evmap( int32_t val, int32_t& last,
	    const multimap<int32_t, PowerEvent*>& evmap, EventDispatcher& evdis);

    void check_evmap( float val, float& last,
	    const multimap<float, PowerEvent*>& evmap, EventDispatcher& evdis);
public:
    PowerManager( SensorManager* sm, Configuration& cf );
    virtual ~PowerManager();

    inline virtual powersensor_type get_type( const power_base& psens ) const
    {
	return psens.get_powersensor_type();
    }

    virtual void register_internal_module( Module* );

    virtual void deregister_module( Module* );

    /**
     * Check all the sensors, should only be called from SensorManager
     */
    virtual void check_sensors( EventDispatcher& );

    /**
     * Register an event for the functor to be called if the specified type is
     * within the specified interval
     */
    PowerEvent& register_power_event( powersensor_type, PSFunctor&, 
	   float low, float up, eh_capabilities what );
    PowerEvent& register_power_event( const power_base&     , PSFunctor&,
	   float low, float up, eh_capabilities what );
    PowerEvent& register_power_event( const uid&     , PSFunctor&,
	   float low, float up, eh_capabilities what );

    PowerEvent& register_power_event( powersensor_type, PSFunctor&, 
	   int32_t low, int32_t up, eh_capabilities what );
    PowerEvent& register_power_event( const power_base&     , PSFunctor&,
	   int32_t low, int32_t up, eh_capabilities what );
    PowerEvent& register_power_event( const uid&     , PSFunctor&,
	   int32_t low, int32_t up, eh_capabilities what );

    /**
     * Register an event for the functor to be called if the types values has changed
     * @warning this can be very noisy
     */
    PowerEvent& register_power_event( powersensor_type, eh_capabilities, PSFunctor& );
    PowerEvent& register_power_event( const power_base& , eh_capabilities, PSFunctor& );
    PowerEvent& register_power_event( const uid& , eh_capabilities, PSFunctor& );




    PowerEvent& deregister_power_event( powersensor_type, PSFunctor&, 
	   float low, float up, eh_capabilities what );
    PowerEvent& deregister_power_event( const power_base&     , PSFunctor&,
	   float low, float up, eh_capabilities what );
    PowerEvent& deregister_power_event( const uid&     , PSFunctor&,
	   float low, float up, eh_capabilities what );

    PowerEvent& deregister_power_event( powersensor_type, PSFunctor&, 
	   int32_t low, int32_t up, eh_capabilities what );
    PowerEvent& deregister_power_event( const power_base&     , PSFunctor&,
	   int32_t low, int32_t up, eh_capabilities what );
    PowerEvent& deregister_power_event( const uid&     , PSFunctor&,
	   int32_t low, int32_t up, eh_capabilities what );

    PowerEvent& deregister_power_event( powersensor_type, eh_capabilities, PSFunctor& );
    PowerEvent& deregister_power_event( const power_base& , eh_capabilities, PSFunctor& );
    PowerEvent& deregister_power_event( const uid& , eh_capabilities, PSFunctor& );

    PowerEvent& deregister_power_event( PowerEvent& );
};

}
}
}
#endif

