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

#ifndef __IWPGDB_H
#include <iwear/db/pgdb.h>
#endif

#ifndef __DEBUGMODULEDB_H
#include <iwear/db/debugmoduledb.h>
#endif

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

#ifndef __LOCATION_H
#include <iwlocator/location.h>
#endif

#ifndef __DEBUGMANAGER_H
#include <iwear/debugmanager.h>
#endif

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

//#ifndef __POLYGON_H
//#include <iwear/polygon.h>
//#endif

//#ifndef __I18N_H
//#include <iwear/i18n.h>
//#endif

#include <iostream>
#include <string>
#include <vector>
#include <queue>


extern "C" {
#include <sys/time.h>
}

using namespace std;
using namespace iwear::db;
using namespace iwear::sensor;
using namespace iwear::sensor::location;

namespace iwear{
    namespace routetracker{
class RTDatabase{
private:

    /**
     * A db database object. This object can supply the query to the
     * routetracker database.
     */
    iwear::db::db* DB;

    /**
     * Tour ID in the tour table.
     */
    int32_t tour_id;

    /**
     * Person ID in the person table.
     */
    int32_t person_id;

    /**
     * Keyword ID in the keyword table.
     */
    int32_t keyword_id;

    /**
     * Waypoint ID in the waypoint table.
     */
    int32_t waypoint_id;

    //int32_t annotation_id;

    /**
     * This function selects the current waypoint id (after a neu
     * waypoint was created) from the waypoint table. Or if a
     * timestamp was specified, it selects then the waypoint id to
     * this timestamp.
     *
     * @param when the timestamp. Default is NULL.
     * @return the waypoint id  
     */
    int32_t select_waypoint_id(const timeval* when = NULL);

    /**
     * This function selects the sensor id of a data sensor type from
     * the data sensors table.
     *
     * @param type the data sensor type.
     * @return the sensor id
     */ 
    int32_t select_sensor_id(const datasensor_type& type);

    /**
     * This function selects the current tour id (after a neu tour was
     * created) from the tour table. Or if a description was given, it
     * selects then the tour id to this specified description.
     *
     * @param description the description of the tour. Default is NULL.    
     * @return the tour id
     */
    int32_t select_tour_id (const string* description = NULL);

    /**
     * This function selects the current keyword id (after a neu
     * keyword was created) from the keyword table. Or if a label was
     * given, it selects then the keyword id to this specified label.
     *
     * @param label the label of the keyword. Default is NULL.    
     * @return the keyword id
     */
    int32_t select_keyword_id(const string* label = NULL);

    /**
     * This function selects the current person id (after a neu person
     * was added) from the person table.
     *
     * @return the person id
     */
    int32_t select_person_id(void);
    
    /**
     * This function selects a series of image ids for the current or
     * a specified waypoint from the images table -- it could be saved
     * several pictures to a same waypoint.
     *
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return a series of image ids
     */
    vector<int32_t> select_image_id(const int32_t& _waypoint_id = -1);

    /**
     * This function gets a series of sound ids for the current or a
     * specified waypoint from the sounds table -- it could be saved
     * several sound files to a same waypoint.
     *
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return a series of sound ids
     */
    vector<int32_t> select_sound_id(const int32_t& _waypoint_id = -1);

    /**
     * This function saves the tour id and corresponding person id in
     * the relation table: r_tour_person.
     */
    void write_r_tour_person(void);

    /**
     * This function saves the tour id and corresponding keyword id in
     * the relation table: r_tour_keyword.
     */    
    void write_r_tour_keyword(void);

protected:

public:

    /**
     * The Constructor.
     */
    RTDatabase();

    /**
     * The Destructor.
     */
    ~RTDatabase();
    
    /**
     * This function does the work on connection to the routetracker
     * database.
     * 
     * @param host the host name
     * @param db the database name
     * @param user the user name
     * @param pw the database password
     * @param dbpar the database parameter
     * @return 0 if connection was done, else -1.
     */
    int32_t get_db_connection(const string& host, const string& db, const string& user, const string& pw, const string& dbpar);

    /**
     * Close the db connection.
     */
    int32_t close_db_connection(void);
    
    /**
     * This function checks if the routetracker database tables
     * exist or not.
     * 
     * @return true if the structure exists, else false.
     */
    bool check_db_tables(); 

    /**
     * This function creates a new tour in the tour table (with a
     * given tour description). After that the class variable
     * tour_id was been refered to the current tour id.   
     *
     * @param description the tour description
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_tour(const string& description); 

    /**
     * This function addes a person record in the person table. After
     * that the class variable person_id was been refered to the
     * current person id and a relation between a tour and the person
     * was been added in the relation table r_tour_person.
     *
     * @param name the person's name
     * @param first_name the person's first name
     * @param login the person's login name
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_person(const string& name, const string& first_name, const string& login);
    
    /**
     * This function addes a keyword record of a tour in the keyword
     * table. After that the class variable keyword_id was been
     * refered to the current keyword id and a relation between a tour
     * and the keyword was been added in the relation table
     * r_tour_keyword.
     *
     * @param label the keyword's label
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_keyword(const string& label);
    
    /**
     * This function creates a new waypoint for the current tour and
     * the current timestamp. Or if a tour or a timestamp was given,
     * it creates then a new waypoint to the specified tour or
     * timestamp. After that the class variable waypoint_id was been
     * refered to the current keyword id.
     *
     * @param _tour_id the given tour id. Default is -1.
     * @param when the given timestamp. Default is NULL.
     * @return 0 on Success. Or errorcode, if any.   
     */
    int32_t create_waypoint(const int32_t& _tour_id = -1, const timeval* when = NULL);

    /**
     * This function adds a value of a data sensor type for the
     * current or a specified waypoint in the data sensor values
     * table.
     * 
     * @param type the data sensor type
     * @param value the sensor value
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_data_sensor_values(const datasensor_type& type, const double& value, const int32_t& _waypoint_id = -1);
    
    /**
     * This function adds a location record for the current or a
     * specified waypoint in the location table.
     * 
     * @param location the Location object
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_location(const Location& location, const int32_t& _waypoint_id = -1);    
    
    /**
     * This function adds a image file for the current or a specified
     * waypoint in the images table.
     * 
     * @param image the image file
     * @param comment the comment of the image
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_image(const string& image, const string& comment, const int32_t& _waypoint_id = -1);
    
    /**
     * This function adds a sound file for the current or a specified
     * waypoint in the sounds table.
     * 
     * @param sound the sound file
     * @param comment the comment of the sound
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t write_sound(const string& sound, const string& comment, const int32_t& _waypoint_id = -1);
    
    //int32_t write_annotation(const int32_t& _waypoint_id = -1, const int32_t& _keyword_id = -1, const string* comment = Null); 
   
    /**
     * This function gets the current waypoint id (after a neu
     * waypoint was created) from the waypoint table. Or if a
     * timestamp was specified, it gets then the waypoint id to this
     * timestamp.
     *
     * @param when the timestamp. Default is NULL.  
     * @return the waypoint id. -1 means that there were no waypoints
     * in the waypoint table.
     */
    int32_t get_waypoint_id(const timeval* when = NULL); 
    
    /**
     * This function gets the current tour id (after a neu tour was
     * created) from the tour table. Or if a description was given, it
     * gets then the tour id to this specified description.
     *
     * @param description the description of the tour. Default is
     * NULL.  
     * @return the tour id. -1 means that there were no tours
     * in the tour table.
     */
    int32_t get_tour_id(const string* description = NULL);
    
    /**
     * This function gets the current keyword id (after a neu keyword
     * was created) from the keyword table. Or if a label was given,
     * it gets then the keyword id to this specified label.
     *
     * @param label the label of the keyword. Default is NULL.
     * @return the keyword id. -1 means that there were no keywords in
     * the keyword table.
     */
    int32_t get_keyword_id(const string* label = NULL); 

    /**
     * This function gets a series of image ids for the current or a
     * specified waypoint from the images table -- it could be saved
     * several pictures to a same waypoint.
     *
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return a series of image ids
     */
    vector<int32_t> get_image_id(const int32_t& _waypoint_id = -1);
 
    /**
     * This function gets a series of sound ids for the current or a
     * specified waypoint from the sounds table -- it could be saved
     * several sound files to a same waypoint.
     *
     * @param _waypoint_id the specified waypoint id. Default is -1.
     * @return a series of sound ids
     */
    vector<int32_t> get_sound_id(const int32_t& _waypoint_id = -1);

    /**
     * This function gets the value of a data sensor type for a
     * specified waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @param type the data sensor type
     * @return the value of the sensor type 
     */
    double get_data_sensor_value(const int32_t& _waypoint_id, const datasensor_type& type);
    
    /**
     * This function gets the location value of a specified waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @return the Location object 
     */
    Location get_location(const int32_t& _waypoint_id);

    /**
     * This function gets a series of image files of a specified
     * waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @return a series of image files
     */ 
    vector<string> get_image(const int32_t& _waypoint_id); 
        
    /**
     * This function gets a series of sound files of a specified
     * waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @return a series of sound files
     */ 
    vector<string> get_sound(const int32_t& _waypoint_id);

    /**
     * This function gets a series of login names for a specified
     * tour.
     *
     * @param _tour_id the specified tour id
     * @return a series of login names
     */ 
    vector<string> get_person_login(const int32_t& _tour_id);
    
    /**
     * This function gets a series of keyword labels for a specified
     * tour.
     *
     * @param _tour_id the specified tour id
     * @return a series of keyword lables
     */ 
    vector<string> get_keyword(const int32_t& _tour_id);
   
    /**
     * This function updates the value of a data sensor type for a
     * specified waypoint with a given new value.
     *
     * @param _waypoint_id the specified waypoint id
     * @param type the type of the data sensor
     * @param new_value the new value
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t update_data_sensor_value(const int32_t& _waypoint_id, const datasensor_type& type, const double& new_value);
   
    /**
     * This function updates the value of a location object for a
     * specified waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @param new_location the Location object with new values
     * @return 0 on Success. Or errorcode, if any.
     */ 
    int32_t update_location(const int32_t& _waypoint_id, const Location& new_location);
    
    /**
     * This function does the same work as update_location() function,
     * but more intelligent. It needn't give a complete new Location
     * object, if not all of the attributes of the object were
     * changed, but only the changed location-attributes and their new
     * values. 
     *
     * This function is used for location-attributes which
     * are string-type.
     *
     * @param _waypoint_id the specified waypoint id
     * @param column the changed location-attributes
     * @param new_value the new values of the attributes (string type)
     * @return 0 on Success. Or errorcode, if any.
     */ 
    int32_t update_location_str(const int32_t& _waypoint_id, queue<string> column, queue<string> new_value);
    
    /**
     * This function does the same work as update_location() function,
     * but more intelligent. It needn't give a complete new Location
     * object, if not all of the attributes of the object were
     * changed, but only the changed location-attributes and their new
     * values.
     *  
     * This function is used for location-attributes which are
     * double-type.
     *
     * @param _waypoint_id the specified waypoint id
     * @param column the changed location-attributes
     * @param new_value the new values of the attributes (double type)
     * @return 0 on Success. Or errorcode, if any.
     */ 
    int32_t update_location_double(const int32_t& _waypoint_id, queue<string> column, queue<double> new_value);
    
    /**
     * This function updates a tour record with the new description.
     *
     * @param _tour_id the specified tour id
     * @param new_description the new tour description
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t update_tour(const int32_t& _tour_id, const string& new_description);
    
    /**
     * This function updates a person record with the new person informations.
     *
     * @param old_login the login name of the person
     * @param new_name the new name of the person
     * @param new_first_name the new first name of the person
     * @param new_login the new login name of the person
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t update_person(const string& old_login, const string& new_name, const string& new_first_name, const string& new_login);
    
    /**
     * This function does the same work as update_person() function,
     * but more intelligent. It needn't give all of the person
     * informations if some of them aren't changed.
     *
     * @param old_login the the login name of the person
     * @param column the changed person-attributes
     * @param new_value the new values of the attributes
     * @return 0 on Success. Or errorcode, if any. 
     */ 
    int32_t update_person_str(const string& old_login, queue<string> column, queue<string> new_value);
    
    /**
     * This function updates the keyword record with a new keyword
     * label.
     *
     * @param old_label the label of the keyword
     * @param new_label the new label of the keyword
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t update_keyword(const string& old_label, const string& new_label);

    /**
     * This function updates a image record.
     *
     * @param image_id the specified image id
     * @param new_image to refer to a new image file for this image
     * id. Default is NULL.
     * @param new_waypoint_id to refer to a other waypoint for this
     * image file. Default is -1. 
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t update_image(const int32_t& image_id, const string* new_image = NULL, const int32_t& new_waypoint_id = -1); 

    /**
     * This function updates a sound record.
     *
     * @param sound_id the specified sound id
     * @param new_sound to refer to a new sound file for this sound
     * id. Default is NULL.
     * @param new_waypoint_id to refer to a other waypoint for this
     * sound file. Default is -1.
     * @return 0 on Success. Or errorcode, if any. 
     */
    int32_t update_sound(const int32_t& sound_id, const string* new_sound = NULL, const int32_t& new_waypoint_id = -1); 
    
    /**
     * This function deletes a tour record.
     *
     * @param _tour_id the specified tour id
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t delete_tour(const int32_t& _tour_id); 

    /**
     * This function deletes a person record.
     *
     * @param login the specified login name of the person
     * @return 0 on Success. Or errorcode, if any. 
     */
    int32_t delete_person(const string& login);

    /**
     * This function deletes a keyword record.
     *
     * @param label the specified label of the keyword
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t delete_keyword(const string& label);

    /**
     * This function deletes a waypoint record.
     *
     * @param _waypoint_id the specified waypoint id
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t delete_waypoint(const int32_t& _waypoint_id);
    
    /**
     * This function deletes a value of a data sensor type for a
     * specified waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @param type the data sensor type
     * @return 0 on Success. Or errorcode, if any. 
     */
    int32_t delete_data_sensor_value(const int32_t& _waypoint_id, const datasensor_type& type);
    
    /**
     * This function deletes a location record for a specified
     * waypoint.
     *
     * @param _waypoint_id the specified waypoint id
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t delete_location(const int32_t& _waypoint_id);
    
    /**
     * This function deletes a image record.
     *
     * @param image_id the specified image id
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t delete_image(const int32_t& image_id); 
    
    /**
     * This function deletes a sound record.
     *
     * @param sound_id the specified sound id
     * @return 0 on Success. Or errorcode, if any.
     */
    int32_t delete_sound(const int32_t& sound_id);

    //int32_t delete_annotation(const int32_t& _waypoint_id, const int32_t& _keyword_id);

}; // class RTDatabase
    } // namespace routetracker
} // namespace iwear

#endif // __RTDATABASE_H

