/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CParams.cpp  -  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"
 ***************************************************************************/

#include <sptk3/CParams.h>
#include <sptk3/CIntList.h>
#include <sptk3/CException.h>

#include <sptk3/string_ext.h>
#include <ctype.h>

using namespace std;
using namespace sptk;

//---------------------------------------------------------------------------
CParam::CParam(char *name) : CVariant() {
   m_name = lowerCase(name);
   m_timeData = new char[64];
   m_callbackLength = 0;
}
//---------------------------------------------------------------------------
CParam::~CParam() {
   delete [] m_timeData;
}
//---------------------------------------------------------------------------
CParam& CParam::operator = (const CParam& param) {
   this->setData(param);
   this->m_bindParamIndexes = param.m_bindParamIndexes;
   return *this;
}
//---------------------------------------------------------------------------
void CParam::bindAdd(unsigned bindIndex) {
   m_bindParamIndexes.push_back(bindIndex);
}
//---------------------------------------------------------------------------
string CParam::asXML() const {
   string xml("<param ");
   xml += "name='" + m_name + "' ";
   xml += "type='" + int2string(m_dataType) + "' ";
   xml += "null='" + int2string(m_null) + "' ";
   if (m_dataType & (VAR_STRING|VAR_TEXT)) {
      string txt = replaceAll(replaceAll(m_data.buffer.data,"\n","\\n"),"\r","");
      xml += "value='" + txt + "' ";
   } else {
      xml += "value='" + asString() + "' ";
   }
   xml += "size='" + int2string(m_dataSize) + "' />";
   return xml;
}
//---------------------------------------------------------------------------
CParamList::~CParamList() {
   try {
      clear();
   }
   catch (...) {}
}
//---------------------------------------------------------------------------
void CParamList::clear() {
   for (unsigned i = 0; i < size(); i++) {
      CParam *item = (CParam *)m_items[i];
      delete item;
   }
   m_items.clear();
   m_index.clear();
   m_paramStreamItor = m_items.begin();
}
//---------------------------------------------------------------------------
void CParamList::add(CParam * item) {
   m_items.push_back(item);
   m_index[item->name()] = item;
   m_paramStreamItor = m_items.begin();
}
//---------------------------------------------------------------------------
CParam& CParamList::operator [] (unsigned index) const {
   if (index >= m_items.size())
      throw CException("Invalid parameter index",__FILE__,__LINE__);
   return *(CParam *)m_items[index];
}
//---------------------------------------------------------------------------
CParam& CParamList::operator [] (int index) const {
   if ((unsigned)index >= m_items.size())
      throw CException("Invalid parameter index",__FILE__,__LINE__);
   return *(CParam *)m_items[index];
}
//---------------------------------------------------------------------------
int CParamList::paramIndex(const char *paramName) {
   map<istring,CParam *>::iterator itor = m_index.find(paramName);
   if (itor == m_index.end())
      return -1;
   return distance(m_index.begin(),itor);
}
//---------------------------------------------------------------------------
CParam& CParamList::operator [] (const char *paramName) const {
   map<istring,CParam *>::const_iterator itor = m_index.find(paramName);
   if (itor == m_index.end())
      throw CException("Invalid parameter name: "+string(paramName),__FILE__,__LINE__);
   return *itor->second;
}
//---------------------------------------------------------------------------
CParam& CParamList::operator [] (const string& paramName) const {
   return operator[] (paramName.c_str());
}
//---------------------------------------------------------------------------
void CParamList::remove(unsigned i) {
   CParam *item = m_items[i];
   m_index.erase(item->name().c_str());
   m_items.erase(m_items.begin()+i);
   delete item;
   m_paramStreamItor = m_items.begin();
}
//---------------------------------------------------------------------------
CParam& CParamList::next() {
   CParam *currentParam = *m_paramStreamItor;
   m_paramStreamItor++;
   if (m_paramStreamItor == m_items.end()) m_paramStreamItor = m_items.begin();
   return *currentParam;
}
//---------------------------------------------------------------------------
CParamList& operator << (CParamList& paramList, const string& data) {
   paramList.next() = data;
   return paramList;
}

CParamList& operator << (CParamList& paramList, const char *data) {
   paramList.next() = data;
   return paramList;
}

CParamList& operator << (CParamList& paramList, int data) {
   paramList.next() = data;
   return paramList;
}

CParamList& operator << (CParamList& paramList, double data) {
   paramList.next() = data;
   return paramList;
}

CParamList& operator << (CParamList& paramList, CDateTime data) {
   paramList.next() = data;
   return paramList;
}

CParamList& operator << (CParamList& paramList, const CBuffer& data) {
   paramList.next() = data;
   return paramList;
}
