/**
 * @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 __IWSENS_SENSORMANAGER_H
#define __IWSENS_SENSORMANAGER_H

#ifndef __IWEAR_BASEMODULEMANAGER_H
#include <iwear/basemodulemanager.h>
#endif

#ifndef __IWSENS_SENSOR_H
#include <iwsens/sensor.h>
#endif

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


#ifndef __IWSENS_SENSORHANDLER_H
#include <iwsens/sensorhandler.h>
#endif

namespace iwear 
{
    class EventDispatcher;
namespace sensor
{

class SensorManager : public ModuleManager<sensor_type,Sensor,BaseModuleManager>
{
private:
    SensorManager() : ModuleManager<sensor_type,Sensor,BaseModuleManager>(NULL, *((Configuration*)0)) {}
protected:
    uint32_t master_interval;
public:
    uint32_t get_master_interval( void ) const { return master_interval; }
    SensorManager( BaseModuleManager*, Configuration& cf );
    inline virtual sensor_type get_type( const Sensor& sens ) const
    {
	return sens.get_sensor_type();
    }

    virtual void register_external_module( Module* );
    virtual void register_internal_module( Module* );

    virtual void deregister_module( Module* );

    inline PManBase* get_locationmanager( void ) const
    {
	map<sensor_type, PManBase* >::const_iterator si(SubManagers.find(location_sensor));
	if( si != SubManagers.end() )
	{
	    return si->second;
	}
	else
	{
	    return 0;
	}
    }

    /**
     * Will lookup a sensor of the requested type (e.g. loudness, temperature
     * etc.) and return its current value.
     * This should simply call the SensorHandler interface of stuff...
     * @note I dont know how the sensorhandler calls its enums for this...
     */
    double get_sensor_data( datasensor_type st = num_datasensor_type );
    std::pair<double,timeval> get_sensor_datatime( datasensor_type st = num_datasensor_type );


    void register_sensor_event( datasensor_type st, double value, DoubleFunctor& df );

    /**
     * Checks all available sensors and dispatches events for them.
     */
    void check_sensors( EventDispatcher& );

    /**
     * This calls the get_location of the location manager and returns the 
     * Primary Problem at this point in implementation is circulary dependency.
     * With the use of this, the core will need the location package and vice
     * versa. We will therefore maybe put these classes into some other library
     * one day....
     */
//    location::IWLocation get_location( location::locator_type lt = location::num_locator_type ); 

//    void register_location_event( location::locator_type lt, const location::IWLocation& w, location::LocFunctor& lf );

    /**
     * Get the IWLocationManager.
     * @return the IWLocationManager.
     */
//    location::IWLocationManager& get_location_manager(void);
    
    /**
     * This calls the function in the sensorhandler. @see SensorHandler
     */
    DataSensorEvent& register_sensor_event( datasensor_type st, DSEFunctor& df
	                , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
        
    /**
     * This calls the function in the sensorhandler. @see SensorHandler
     */
    DataSensorEvent& register_sensor_event( const uid&, DSEFunctor& df
			, double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
	    
    /**
     * This calls the function in the sensorhandler. @see SensorHandler
     */
    DataSensorEvent& register_sensor_event( const DataSensor&, DSEFunctor& df
			, double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );

    /**
     * Deregisters a specific event.
     * @see SensorHandler
     */
    void deregister_sensor_event( const DataSensorEvent& );

    /**
     * Deregister an event according to the data passed at registration.
     * @see SensorHandler
     */
    void deregister_sensor_event( datasensor_type st, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
    /**
     * Deregister an event according to the data passed at registration.
     * @see SensorHandler
     */
    void deregister_sensor_event( const uid&, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
    /**
     * Deregister an event according to the data passed at registration.
     * @see SensorHandler
     */
    void deregister_sensor_event( const DataSensor&, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );

};

}
}
#endif
