/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is a part of The iWear Framework.
 * In particular is this file a part of the Framework Context 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 __SENSORCONTEXT_H
#define __SENSORCONTEXT_H

#ifndef __SENSOR_ENUM_H
#include <iwsens/sensor_enum.h>
#endif

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

#ifndef __ATOMICCONTEXT_H
#include <iwear-context/atomiccontext.h>
#endif

#ifndef __CONTEXT_ENUM_H
#include <iwear-context/contextenums.h>
#endif

#ifndef __CONSTANTS_H
#include <iwear/constants.h>
#endif

#ifndef __SENSOREVENTFUNCTOR_H
#include <iwear-context/sensoreventfunctor.h>
#endif

#ifndef __UTILITY_H
#include <iwear/utility.h>
#endif

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

using namespace std;

namespace iwear{
namespace context{
// forward declaration
class ContextManager;
class SensorContext : public AtomicContext{
private:
    /**
     * The type of the data this SensorContext works with - e.g. TEMPERATURE.
     */
    SensorType sensor_type;

    /**
     * The type of the related DataSensor.
     */
    iwear::sensor::datasensor_type related_datasensor_type;

    /**
     * The last value we got from the sensor.
     */
    double sensor_value;

    /**
     * The value to compare the sensor_value with.
     */
    double comp_value;

    /**
     * The comparison-operator to be used.
     */
    Comparison comparison;

    /**
     * The unit of the values.
     */
    units unit;

    /**
     * How accurate the "equals"-comparison should be - +/- the given
     * accuracy-value will count as being equal.
     */
    double accuracy;

    /**
     * We get this from the SensorManager when we register and need it to
     * deregister later.
     */
    iwear::sensor::DataSensorEvent* datasensorevent;

    /**
     * With that we register at the SensorManager - the functor is called if
     * the event occurs.
     */
    SensorEventFunctor* sensor_event_functor;

    /**
     * This constructor is private to prevent people from using it.
     */
    SensorContext(void)
	: AtomicContext("invalid", num_AtomicType)
    {
    }
protected:
public:
    /**
     * The constructor to be used.
     *
     * @param name the name of the context.
     *
     * @param sensor_type the type of the sensor.
     *
     * @param comp_value the comparison value.
     *
     * @param comparison how to compare - greater, equals etc.
     *
     * @param unit the unit of the value.
     *
     * @param accuracy how much the value may differ from the compare
     * value. This can also be used to define intervals.
     */
    SensorContext(const string& name, 
		  SensorType sensor_type,
		  double comp_value,
		  Comparison comparison, 
		  units unit, 
		  double accuracy = 0);
    
    /**
     * The destructor of the SensorContext.
     */
    virtual ~SensorContext(void);

    /**
     * Get the type of the related sensor.
     *
     * @return the type of the related DataSensor.
     */
    iwear::sensor::datasensor_type get_related_datasensor_type(){
	return related_datasensor_type;
    }

    /**
     * Get the comparison value of this sensor context.
     *
     * @return the comparison value.
     */
    double get_comp_value(){
	return comp_value;
    }

    /**
     * How the comparison value and the actual sensor value are compared.
     *
     * @return the type of the comparison.
     */
    Comparison get_comparison(){
	return this->comparison;
    }

    /**
     * Set the crucial information.
     *
     * @param sensor_value the actual value measured.
     * @param active if the sensor is triggered as true.
     * @param timestamp when the value has been measured.
     */
    void set_values(double sensor_value, bool active, timeval timestamp){
	this->sensor_value = sensor_value;
	this->value = active;
	this->last_change = timestamp;
    }
    
    /**
     * Just a mapping from out data types to the sensor data types.
     *
     * @param sensor_type the sensor type to be mapped.
     *
     * @return the mapped type from the sensor.
     */
    iwear::sensor::datasensor_type map_to_datasensor_type(SensorType sensor_type);

    /**
     * We get the given event from the SensorManager and save it here.
     */
    void set_datasensorevent(iwear::sensor::DataSensorEvent& dse){
	this->datasensorevent = &dse;
    }

    /**
     * Get the DataSensorEvent we got when we registered at the SensorManager.
     */
    const iwear::sensor::DataSensorEvent& get_datasensorevent() const{
	return *(this->datasensorevent);
    }

    /**
     * The SensorEventFunctor belonging to this SensorContext will be deleted
     * when this object is destroyed.
     *
     * @param sensor_event_functor the SensorEventFunctor belonging to this SensorContext.
     */
    void create_sensor_event_functor(ContextManager* context_manager){
	this->sensor_event_functor = new SensorEventFunctor(context_manager, this);
	d_dbg << ANSI_YELLOW << __FFL__ << ":\n\t" << ANSI_NORMAL 
	      << "created sensor event functor for " << this->name << endl;

    }

    /**
     * Get the SensorEventFunctor belonging to this SensorContext.
     *
     * @return the SensorEventFunctor belonging to this SensorContext.
     */
    SensorEventFunctor* get_sensor_event_functor(void){
	return sensor_event_functor;
    }

    /**
     * Because the registration at the SensorManager always needs lower and
     * upper bound of an interval (everything is handled through intervals) we
     * calculate the bounds from comp_value, accuracy and comparison.
     */
    double get_lower(void);

    /**
     * Because the registration at the SensorManager always needs lower and
     * upper bound of an interval (everything is handled through intervals) we
     * calculate the bounds from comp_value, accuracy and comparison.
     */
    double get_upper(void);

}; // class SensorContext
} // namespace context
} // namespace iwear
#endif // __SENSORCONTEXT_H
