/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CParams.h  -  description
                             -------------------
    begin                : Tue Dec 14 1999
    copyright            : (C) 1999-2006 by Alexey Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CPARAMS_H__
#define __CPARAMS_H__

#include <sptk3/sptk.h>
#include <sptk3/sptk.h>
#include <sptk3/istring.h>
#include <sptk3/CStrings.h>
#include <sptk3/CVariant.h>
#include <sptk3/CBuffer.h>
#include <sptk3/CIntList.h>

#include <vector>
#include <map>

namespace sptk {

   /// @addtogroup Database Database Support
   /// @{

   /// @brief SQL query parameter. 
   ///
   /// Simplifies the ODBC parameter binding.
   /// Automatically handles most of the data conversions on assignments.
	class SP_EXPORT CParam : public CVariant {
		friend class CQuery;
		friend class CParamList;

		std::string       m_name;              ///< Parameter name
		CIntList          m_bindParamIndexes;  ///< The list of SQL query parameter numbers with this name

	protected:

		char             *m_timeData;          ///< Special memory allocated for time structures
		INTEGER32         m_callbackLength;    ///< An integer reserved to callback parameter data length

	public:   
      /// Clears internal parameter binding index
		void     bindClear() { m_bindParamIndexes.clear(); }

      /// Adds internal parameter binding index
		void     bindAdd(unsigned bindIndex);

      /// Returns internal parameter binding count
		unsigned bindCount() { return m_bindParamIndexes.size(); }

      /// Returns the parameter bing position by index in the binding list
		unsigned bindIndex(unsigned ind) { return m_bindParamIndexes[ind]; }

      /// Returns the internal small conversion buffer used to convert the
      /// date structure to SPTK. Please, don't use it.
		char *conversionBuffer() { return m_timeData; }

      /// An integer reserved to callback parameter data length
		INTEGER32& callbackLength() { return m_callbackLength; }

	public:

      /// Constructor
      /// @param name char *, parameter name
		CParam(char *name);

      /// Destructor
		~CParam();

      /// Returns parameter name
		std::string name() const { return m_name; }

      /// Assign operator
		CParam& operator = (const CParam& param);

      /// Assign operator
		CParam& operator = (const CVariant& param) { if (this == &param) return *this; setData(param); return *this; };

      /// Assign operator
		CParam& operator = (int v)                 { setInteger(v); return *this; }

      /// Assign operator
		CParam& operator = (unsigned v)            { setInteger(v); return *this; }

      /// Assign operator
		CParam& operator = (float v)               { setFloat(v);   return *this; }

      /// Assign operator
		CParam& operator = (double v)              { setFloat(v);   return *this; }

      /// Assign operator
		CParam& operator = (const char *s)         { setString(s);  return *this; }

      /// Assign operator
		CParam& operator = (const std::string& s)  { setString(s.c_str()); return *this; }

      /// Assign operator
		CParam& operator = (const CDateTime& dt)   { setDateTime(dt); return *this; }

      /// Returns parameter info as XML
		std::string asXML() const;
	};

   /// @brief Query parameters list. 
   /// 
   /// Has internal index to speed up the parameter search by name.
   /// @see CQuery 
   /// @see CParam
	class SP_EXPORT CParamList {
		friend class CQuery;

		std::vector<CParam *>            m_items;	         ///< The list of parameters
		std::vector<CParam *>::iterator  m_paramStreamItor;   ///< The list of parameters iterator
		std::map<istring,CParam *>       m_index;             ///< The parameters index
	protected:   
      /// Adds a parameter to the list
		void     add(CParam *item);

	public:

      /// Default constructor
		CParamList() { m_paramStreamItor = m_items.begin(); };

      /// Destructor
		~CParamList();

      /// Removes all the parameters from the list,
      /// and releases any allocated resources
		void     clear();

      /// Returns parameter index by name
      /// @param paramName const char *, parameter name
      /// @returns parameter index, or -1 if not found
		int      paramIndex(const char *paramName);

      /// Removes a parameter from the list and from the memory.
      /// @param ndx unsigned, parameter index in the list
		void     remove(unsigned ndx);

      /// Parameter access by index
      /// @param index unsigned, parameter index
		CParam&  operator[] (unsigned index) const;

      /// Parameter access by index
      /// @param index int, parameter index
		CParam&  operator[] (int index) const;

      /// Parameter access by name
      /// @param paramName const char *, parameter name
		CParam&  operator[] (const char *paramName) const;

      /// Parameter access by name
      /// @param paramName const std::string&, parameter name
		CParam&  operator[] (const std::string& paramName) const;

      /// Returns parameter count
		unsigned size() const { return m_items.size(); }

      /// Sets the parameter stream iterator to the first parameter
		void rewind() { m_paramStreamItor = m_items.begin(); }

      /// Sets the parameter stream iterator to the next parameter.
      /// After the last parameter is reached, the iterator is switch to the first parameter
      /// @returns current parameter
		CParam& next();
	};
}

/// Streamed parameter assign. The data is assigned to the current parameter,
/// and then next parameter becomes current. The rewind() method is called
/// automatically to reset the parameter iterator to the first parameter upon
/// query exec() or open() method calls.
/// @param paramList CParamList&, a list of parameters to assign
/// @param data const std::string, a data to assign to current parameter
SP_EXPORT sptk::CParamList& operator << (sptk::CParamList& paramList, const std::string& data);

/// Streamed parameter assign. The data is assigned to the current parameter,
/// and then next parameter becomes current. The rewind() method is called
/// automatically to reset the parameter iterator to the first parameter upon
/// query exec() or open() method calls.
/// @param paramList CParamList&, a list of parameters to assign
/// @param data const char *, a data to assign to current parameter
SP_EXPORT sptk::CParamList& operator << (sptk::CParamList& paramList, const char *data);

/// Streamed parameter assign. The data is assigned to the current parameter,
/// and then next parameter becomes current. The rewind() method is called
/// automatically to reset the parameter iterator to the first parameter upon
/// query exec() or open() method calls.
/// @param paramList CParamList&, a list of parameters to assign
/// @param data int, a data to assign to current parameter
SP_EXPORT sptk::CParamList& operator << (sptk::CParamList& paramList, int data);

/// Streamed parameter assign. The data is assigned to the current parameter,
/// and then next parameter becomes current. The rewind() method is called
/// automatically to reset the parameter iterator to the first parameter upon
/// query exec() or open() method calls.
/// @param paramList CParamList&, a list of parameters to assign
/// @param data double, a data to assign to current parameter
SP_EXPORT sptk::CParamList& operator << (sptk::CParamList& paramList, double data);

/// Streamed parameter assign. The data is assigned to the current parameter,
/// and then next parameter becomes current. The rewind() method is called
/// automatically to reset the parameter iterator to the first parameter upon
/// query exec() or open() method calls.
/// @param paramList CParamList&, a list of parameters to assign
/// @param data CDateTime, a data to assign to current parameter
SP_EXPORT sptk::CParamList& operator << (sptk::CParamList& paramList, sptk::CDateTime data);

/// Streamed parameter assign. The data is assigned to the current parameter,
/// and then next parameter becomes current. The rewind() method is called
/// automatically to reset the parameter iterator to the first parameter upon
/// query exec() or open() method calls.
/// @param paramList CParamList&, a list of parameters to assign
/// @param data const CBuffer&, a data to assign to current parameter
SP_EXPORT sptk::CParamList& operator << (sptk::CParamList& paramList, const sptk::CBuffer& data);

/// @}

#endif
