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

#ifndef __THREAD_H
#include <iwear/thread.h>
#endif

#ifndef __APPLICATION_H
#include <iwear_uiservices/application.h>
#endif

#ifndef __INPUTENUMS_H
#include <iwear_input/inputenums.h>
#endif

#ifndef __CONTEXT_XML_HANDLER_H_
#include <iwear_utils_xml/xmlhandler.h>
#endif

#ifndef __ROUTE_H
#include <iwear_routetracker/route.h>
#endif

#ifndef __RTDATABASE_H
#include <iwear_routetracker/rtdatabase.h>
#endif

#ifndef __SIGNALINPUTDATA_H
#include <iwear_input/signalinputdata.h>
#endif

#ifndef __SENSORMANAGER_H
#include <iwsens/sensormanager.h>
#endif

#ifndef __SIGNALDATA_H
#include <iwear_output/signaldata.h>
#endif

#include <queue>

using namespace std;
using namespace iwear::xml;
using namespace iwear::uiservices;



namespace iwear{
namespace uiservices{
// forward declarations
    class ServiceManager;
    class ApplicationService;
}
namespace routetracker{

// forward declarations
class DataCollector;
class RouteTrackerSignalInputFunctor;

class RouteTracker : public Application{
private:
    SensorManager* sensor_manager;
    RTDatabase database;
    queue<SignalInputData> status_changes;

    DataCollector* data_collector;

    InputSignal former_status;
    InputSignal status;
//    SignalInputData* last_button_input;

    int frozen_waypoint_id;

    RouteTrackerSignalInputFunctor* functor_activated; 
    RouteTrackerSignalInputFunctor* functor_pre_activation; 

    iwear::output::SignalData output_data;

    ////////////////////////////
    // values from the config //
    ////////////////////////////

    // route-specific config
    Route* defaultroute;
    vector<Route*> routes;
    vector<Route*>::iterator current_route;

    // sysconfig - independant from current route
    string db_name;
    string db_host;
    string db_user;
    string db_password;


//    void read_config( void );

    /**
     * This method gets a new SignalInputData from the queue, extracts the
     * InputSignal and saves it in status (the old value is saved in
     * formaer_status). By default the method waits until the next Signal
     * drops in. By changing the parameter timeout one can force the method to
     * return after waiting at most the given timeout. Then the status and
     * former_status are not changed.
     *
     * @param timeout How log to wait at most for a signal. Default is 0 and
     * means to wait until a signal arrives.
     *
     * @return The InputSignal that occured lately or num_InputSignal if there
     * was no Signal within the given timeout.
     */
    InputSignal get_next_status( float timeout = 0);

    

    /**
     * Is called if the button on the IOWarrior is pressed.
     *
     * @param waypoint_id The id of the waypoint - needed for writing in the
     * database.
     */
    void button_pushed(int waypoint_id = -1);

    void start_sound_recording( void );

    void stop_sound_recording( void );

    /**
     * Accessing the status_changes variable has to be exclusive - so this
     * method is threadlocked against the other status_changes-methods.
     *
     * @return if there are status changes in the queue.
     */
    bool status_changes_empty(void);

    /**
     * Accessing the status_changes variable has to be exclusive - so this
     * method is threadlocked against the other status_changes-methods.
     *
     * @return the next status change from the queue.
     * @note the status change is also popped from the queue!
     */
    InputSignal status_changes_pop_front(void);

    iwear::sensor::datasensor_type map_to_datasensor_type(const string& dst_str);

protected:

    virtual void Run( void );

public:

    RouteTracker(ApplicationService* as,
		 SensorManager* sensman);


    ~RouteTracker( void );

    virtual void Final_Application( void );

    virtual void Init_Application( void );

    virtual void Reset_Application( void );

    virtual void Suspend_Application( void );

    virtual void Pause_Application( void );

    virtual void Resume_Application( void );

    void handle_status_1( void );
    void handle_status_2( void );
    void handle_status_3( void );
    void handle_status_4( void );
	
    virtual const string get_name( void ) { return "RouteTracker"; }

    virtual service_type get_type( void ) { return service_generic; }

    /**
     * Accessing the status_changes variable has to be exclusive - so this
     * method is threadlocked against the other status_changes-methods.
     * 
     * @param data the SignalInputData to be added.
     *
     * @note this method is called by the functors that are registered at the
     * InputManager.
     */
    void status_changes_push(const SignalInputData* data);

    virtual void set_default_configuration(void);
}; // class RouteTracker
} // namespace routetracker
} // namespace iwear

#endif // __ROUTETRACKER_H
