/* +---------------------------------------------------------------------------+
   |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
   |                                                                           |
   |                   http://mrpt.sourceforge.net/                            |
   |                                                                           |
   |   Copyright (C) 2005-2008  University of Malaga                           |
   |                                                                           |
   |    This software was written by the Perception and Robotics               |
   |      research group, University of Malaga (Spain).                        |
   |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
   |                                                                           |
   |  This file is part of the MRPT project.                                   |
   |                                                                           |
   |     MRPT 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, either version 3 of the License, or     |
   |     (at your option) any later version.                                   |
   |                                                                           |
   |   MRPT 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 MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
   |                                                                           |
   +---------------------------------------------------------------------------+ */
#ifndef CSimpleDatabase_H
#define CSimpleDatabase_H

#include <MRPT/UTILS/utils_defs.h>
#include <MRPT/UTILS/CSerializable.h>

namespace UTILS
{

/**  This class implements the tables of databases.
 * \sa CSimpleDatabase
 */
class CSimpleDatabaseTable : public UTILS::CSerializable
{
	// This must be added to any CSerializable derived class:
	DEFINE_SERIALIZABLE( CSimpleDatabaseTable )
public:
	/** Default constructor
	  */
	CSimpleDatabaseTable( );

	/** Destructor
	  */
	virtual ~CSimpleDatabaseTable();

	/** Get the count of fields.
	  */
	size_t fieldsCount() const;

	/** Append a new and empty record at the end of the table, and return the index of the newly added record.
	  */
	size_t appendRecord();

	/** Add a new field to the table. The table is cleared in this operation.
	  */
	void  addField(const char *fieldName);

	/** Get the name of a field by its index
	  * \exception std::exception On index out of bounds
	  */
	std::string  getFieldName(size_t fieldIndex) const;

	/** Get the index for a given field name
	  * \exception std::exception On field not found
	  */
	size_t fieldIndex(const char *fieldName) const;

	/** Get the records count in the table
	  */
	size_t getRecordCount() const;

	/**  Returns the cell content of the record indicates by its index, and the field indicated in "field".
	  * \exception std::exception On field or record not found
	  */
	std::string  get(size_t recordIndex, std::string field) const;

	/**  Returns the cell content of the record indicates by its index, and the field indicated by its index.
	  * \exception std::exception On field or record not found
	  */
	std::string  get(size_t recordIndex, size_t fieldIndex) const;

	/**  Sets the cell content of the record indicates by its index, and the field indicated in "field".
	  * \exception std::exception On field or record not found
	  */
	void  set(size_t recordIndex, std::string field, std::string value);

	/**  Sets the cell content of the record indicates by its index, and the field indicated by its index.
	  * \exception std::exception On field or record not found
	  */
	void  set(size_t recordIndex, size_t fieldIndex, std::string value);

	/**  Executes a query in the table, returning the record index which a given field has a given value, case insensitive, or -1 if not found.
	  */
	int  query(std::string field, std::string value) const;

private:
	/** Field names
	  */
	vector_string				field_names;

	/** Cells data
	  */
	std::vector<vector_string>	data;

}; // end of class definition

	// This must be added to any CSerializable derived class:
	DEFINE_SERIALIZABLE_POST( CSimpleDatabaseTable )

/**  This class impements a very simple database system. A database is
  *   a collection of tables, each one being a CSimpleDatabaseTable object. Tables are
  *   a rectangular arrrangement of cells, organized as records of fields.
  *  There are XML export/import methods in saveAsXML, loadFromXML.
  *
  * \todo Make this thread-safe.
  *
  * \sa CSimpleDatabaseTable
  */
class CSimpleDatabase  : public UTILS::CSerializable
{
	// This must be added to any CSerializable derived class:
	DEFINE_SERIALIZABLE( CSimpleDatabase )

public:
	/** Default constructor
	  */
	CSimpleDatabase( );

	/** Destructor
	  */
	virtual ~CSimpleDatabase( );

	/** Clears the DB.
	  */
	void  clear();

	/** Creates a new table in the DB, initially empty.
	  */
	CSimpleDatabaseTable *  createTable(const std::string &name);

	/** Returns the table with the indicated name
	  * \exception std::exception On table not found.
	  */
	CSimpleDatabaseTable *  getTable(const char *tableName);

	/** Returns the table by index.
	  * \exception std::exception On index out of bounds
	  */
	CSimpleDatabaseTable *  getTable(size_t tableIndex);

	/** Returns the tables count in the DB.
	  */
	size_t	 tablesCount() const;

	/** Returns the tables names in the DB.
	  * \exception std::exception On index out of bounds
	  */
	std::string	 tablesName(size_t tableIndex) const;

	/** Saves this database as a XML file.
	  * \return false on any error, true if successful.
	  * \sa loadFromXML
	  */
	bool saveAsXML( const std::string &fileName ) const;

	/** Loads the content of this database from a a XML file.
	  * \return false on any error, true if successful.
	  * \sa saveAsXML
	  */
	bool loadFromXML( const std::string &fileName );


private:
	/** The tables of the DB and their names:
	  */
	std::vector<CSimpleDatabaseTable*>	tables;
	vector_string						table_names;


}; // end of class definition

	// This must be added to any CSerializable derived class:
	DEFINE_SERIALIZABLE_POST( CSimpleDatabase )

} // End of namespace


#endif

