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

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

#ifndef __IWSENS_DATASENSOR_H
#include <iwsens/datasensor.h>
#endif

#ifndef __IWSENS_DATASENSOREVENT_H
#include <iwsens/datasensorevent.h>
#endif

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

namespace iwear 
{
    namespace sensor
    {
class SensorManager;

/**
 * The Sensor Handler keeps track of the DataSensors that gather some real
 * data.
 */    
class SensorHandler : public ModuleManager<datasensor_type,DataSensor,SensorManager>, public SensorChecking
{
private:
    /**
     * We dont whant a single SensorHandler
     */
    SensorHandler() : ModuleManager<datasensor_type,DataSensor,SensorManager>(NULL, *((Configuration*)0)) { }
protected:
    uint32_t check_interval;
    /**
     * Saves the time at which the next check of a sensor(s) can be done.
     */
    timeval next_check;
    /**
     * This map keeps track of DataSensorEvents per single sensor. The double
     * in the pair is the value of the last update. The double in the multimap
     * is the upper bound of the interval the DataSensorEvent is responsible
     * for.
     */
    map<const DataSensor*,pair<double, multimap<double, DataSensorEvent*> > > SensEvMap;
    
    /**
     * Although this does not really need to be a multimap and can be a list
     * instead, we take a map because we might want to remove the events
     * faster...
     * While using it we will need to iterate over them..
     */
    multimap<const DataSensor*, pair< pair<double, double>, 
	pair<const DataSensor*, DataSensorEvent*> > > SensDDMap;

    /**
     * This is the same as SensEvMap but sorts for some datasensor_type instead
     * of a single sensor.
     */
    map<datasensor_type,pair<double, multimap<double, DataSensorEvent*> > > STEvMap;

    /**
     * Registers some DataSensor via Base class Module. Throws exception in
     * case its not real DataSensor.
     */
    virtual void register_external_module( Module* );

    /**
     * This cehcks all sensors if they need to dispatch an event to the event
     * dispatcher passed.
     */
    void check_all_sensors( EventDispatcher&);

    /**
     * Since we have to check for single sensors, and sensor types, we do the
     * real checking generically for an event holding map. The last double
     * value is passed as a reference, so it can be set to the val.
     */
    void check_evmap( double val, double& last, const multimap<double, DataSensorEvent*>&, EventDispatcher& evdis);

    /**
     * This does a cleanup. Usually, if the SensorHandler will be destroyed,
     * this function is called. It removes every event etc.. If an event has
     * not been removed, before the SensorHandler is destroyed, then probably
     * some other object that registered an event has not deactivated it
     * properly.
     */
    void cleanup( void );

public:
    /**
     * Every instance of a SensorHandler needs a SensorManager as its master.
     */
    SensorHandler( SensorManager* sensman, Configuration& cf );

    /**
     * This destroys the SensorHandler, and frees all resources via calling cleanup()
     */
    virtual ~SensorHandler( );

    /**
     * Call wrapper for getting type of a sensor through generic interface.
     */
    inline virtual datasensor_type get_type( const DataSensor& sens ) const
    {
	return sens.get_datasensor_type(); 
    }

    /**
     * Internally registers a Module. Every Module should call this.
     */
    virtual void register_internal_module( Module* );

    /**
     * and this deregisters a specific module. Every Module is
     * auto-deregistered at destruction, so a user should never call this.
     */
    virtual void deregister_module( Module* );

    /**
     * This gets some data of a specific Type. If there is no sensor for the
     * desired type, it throws some error.
     */
    double get_sensor_data( datasensor_type st = num_datasensor_type );

    /**
     * This returns a pair of the value and the time when it was last changed.
     * Might be now for always-online sensors, and some older value for
     * cyclically updated values (most values are such).
     */
    std::pair<double,timeval> get_sensor_datatime( datasensor_type st = num_datasensor_type );

    /**
     * This registers an event for a certain type of sensor. 
     * @param df is a DSEFunctor that will be called when the event is
     * delivered ( in context of the event dispatcher probably )
     * @param low Is the lower limit of the interval where the event should be triggered.
     * @param up is the upper value at which the interval is leaved.
     * @note The interval is inclusive, so for a certain val the check is low <= val and val <= up.
     */
    DataSensorEvent& register_sensor_event( datasensor_type st, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
    /**
     * This registers an event for a sensor according to the sensors uid. If
     * the sensor was not found, this throws an exception.
     */
    DataSensorEvent& register_sensor_event( const uid&, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
    /**
     * This registers an event for a certain sensor. Should be the standard
     * case.
     */
    DataSensorEvent& register_sensor_event( const DataSensor&, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );

    DataSensorEvent& register_sensor_event( const DataSensor&, const DataSensor&, 
	    DSEFunctor& df, double epsilon );

    void deregister_sensor_event( const DataSensor&, const DataSensor&, double epsilon );
    /**
     * Deregisters a specifig event.
     */
    void deregister_sensor_event( const DataSensorEvent& );

    /**
     * Deregister an event according to the data passed at registration.
     * @see register_sensor_event
     */
    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 register_sensor_event
     */
    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 register_sensor_event
     */
    void deregister_sensor_event( const DataSensor&, DSEFunctor& df
	    , double low = numeric_limits<double>::min(), double up = numeric_limits<double>::max() );
    /**
     * This will be called by the SensorSurveillance service to check all
     * sensors for events.
     */
    virtual void check_sensors( EventDispatcher&);

};

} // namespace sensor
}
#endif

