/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CParams.h  -  description
                             -------------------
    begin                : Tue Dec 14 1999
    copyright            : (C) 1999-2005 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-config.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>

/// @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; }
};

/// @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();

   /// 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 CParamList& operator << (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 CParamList& operator << (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 CParamList& operator << (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 CParamList& operator << (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 CParamList& operator << (CParamList& paramList, 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 CParamList& operator << (CParamList& paramList, const CBuffer& data);

/// @}

#endif
