/***************************************************************************
 *   Copyright (C) 2004-2007 by Joachim Eibl                               *
 *   joachim.eibl at gmx.de                                                   *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.           *
 ***************************************************************************/

#include "common.h"
#include <map>
#include <tqfont.h>
#include <tqcolor.h>
#include <tqsize.h>
#include <tqpoint.h>
#include <tqstringlist.h>
#include <tqtextstream.h>

ValueMap::ValueMap()
{
}

ValueMap::~ValueMap()
{
}

void ValueMap::save( TQTextStream& ts )
{
   std::map<TQString,TQString>::iterator i;
   for( i=m_map.begin(); i!=m_map.end(); ++i)
   {
      TQString key = i->first;
      TQString val = i->second;
      ts << key << "=" << val << "\n";
   }
}

TQString ValueMap::getAsString()
{
   TQString result;
   std::map<TQString,TQString>::iterator i;
   for( i=m_map.begin(); i!=m_map.end(); ++i)
   {
      TQString key = i->first;
      TQString val = i->second;
      result += key + "=" + val + "\n";
   }
   return result;
}

void ValueMap::load( TQTextStream& ts )
{
   while ( !ts.eof() )
   {                                 // until end of file...	   
      TQString s = ts.readLine();         // line of text excluding '\n'
      int pos = s.find('=');
      if( pos > 0 )                     // seems not to have a tag
      {
         TQString key = s.left(pos);
         TQString val = s.mid(pos+1);
         m_map[key] = val;
      }
   }
}
/*
void ValueMap::load( const TQString& s )
{
   int pos=0;
   while ( pos<(int)s.length() )
   {                                 // until end of file...
      int pos2 = s.find('=', pos);
      int pos3 = s.find('\n', pos2 );
      if (pos3<0)
         pos3=s.length();
      if( pos2 > 0 )                     // seems not to have a tag
      {
         TQString key = s.mid(pos, pos2-pos);
         TQString val = s.mid(pos2+1, pos3-pos2-1);
         m_map[key] = val;
      }
      pos = pos3;
   }
}
*/

// safeStringJoin and safeStringSplit allow to convert a stringlist into a string and back
// safely, even if the individual strings in the list contain the separator character.
TQString safeStringJoin(const TQStringList& sl, char sepChar, char metaChar )
{
   // Join the strings in the list, using the separator ','
   // If a string contains the separator character, it will be replaced with "\,".
   // Any occurances of "\" (one backslash) will be replaced with "\\" (2 backslashes)
   
   assert(sepChar!=metaChar);
   
   TQString sep;
   sep += sepChar;
   TQString meta;
   meta += metaChar;   
   
   TQString safeString;
   
   TQStringList::const_iterator i;
   for (i=sl.begin(); i!=sl.end(); ++i)
   {
      TQString s = *i;
      s.replace(meta, meta+meta);   //  "\" -> "\\"
      s.replace(sep, meta+sep);     //  "," -> "\,"
      if ( i==sl.begin() )
         safeString = s;
      else
         safeString += sep + s;
   }
   return safeString;
}

// Split a string that was joined with safeStringJoin
TQStringList safeStringSplit(const TQString& s, char sepChar, char metaChar )
{
   assert(sepChar!=metaChar);
   TQStringList sl;
   // Miniparser
   int i=0;
   int len=s.length();
   TQString b;
   for(i=0;i<len;++i)
   {
      if      ( i+1<len && s[i]==metaChar && s[i+1]==metaChar ){ b+=metaChar; ++i; }
      else if ( i+1<len && s[i]==metaChar && s[i+1]==sepChar ){ b+=sepChar; ++i; }
      else if ( s[i]==sepChar )  // real separator
      {
         sl.push_back(b);
         b="";
      }
      else { b+=s[i]; }
   }
   if ( !b.isEmpty() )
      sl.push_back(b);

   return sl;
}



static TQString numStr(int n)
{
   TQString s;
   s.setNum( n );
   return s;
}

static TQString subSection( const TQString& s, int idx, char sep )
{
   int pos=0;
   while( idx>0 )
   {
      pos = s.find( sep, pos );
      --idx;
      if (pos<0) break;
      ++pos;
   }
   if ( pos>=0 )
   {
      int pos2 = s.find( sep, pos );
      if ( pos2>0 )
         return s.mid(pos, pos2-pos);
      else
         return s.mid(pos);
   }

   return "";
}

static int num( TQString& s, int idx )
{
   return subSection( s, idx, ',').toInt();
}

void ValueMap::writeEntry(const TQString& k, const TQFont& v )
{
   m_map[k] = v.family() + "," + TQString::number(v.pointSize()) + "," + (v.bold() ? "bold" : "normal");
}

void ValueMap::writeEntry(const TQString& k, const TQColor& v )
{
   m_map[k] = numStr(v.red()) + "," + numStr(v.green()) + "," + numStr(v.blue());
}

void ValueMap::writeEntry(const TQString& k, const TQSize& v )
{
   m_map[k] = numStr(v.width()) + "," + numStr(v.height());
}

void ValueMap::writeEntry(const TQString& k, const TQPoint& v )
{
   m_map[k] = numStr(v.x()) + "," + numStr(v.y());
}

void ValueMap::writeEntry(const TQString& k, int v )
{
   m_map[k] = numStr(v);
}

void ValueMap::writeEntry(const TQString& k, bool v )
{
   m_map[k] = numStr(v);
}

void ValueMap::writeEntry(const TQString& k, const TQString& v )
{
   m_map[k] = v;
}

void ValueMap::writeEntry(const TQString& k, const char* v )
{
   m_map[k] = v;
}

void ValueMap::writeEntry(const TQString& k, const TQStringList& v, char separator )
{
   m_map[k] = safeStringJoin(v, separator);
}


TQFont ValueMap::readFontEntry(const TQString& k, TQFont* defaultVal )
{
   TQFont f = *defaultVal;
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      f.setFamily( subSection( i->second, 0, ',' ) );
      f.setPointSize( subSection( i->second, 1, ',' ).toInt() );
      f.setBold( subSection( i->second, 2, ',' )=="bold" );
      //f.fromString(i->second);
   }

   return f;
}

TQColor ValueMap::readColorEntry(const TQString& k, TQColor* defaultVal )
{
   TQColor c= *defaultVal;
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      TQString s = i->second;
      c = TQColor( num(s,0),num(s,1),num(s,2) );
   }

   return c;
}

TQSize ValueMap::readSizeEntry(const TQString& k, TQSize* defaultVal )
{
   TQSize size = defaultVal ? *defaultVal : TQSize(600,400);
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {

      TQString s = i->second;
      size = TQSize( num(s,0),num(s,1) );
   }

   return size;
}

TQPoint ValueMap::readPointEntry(const TQString& k, TQPoint* defaultVal)
{
   TQPoint point = defaultVal ? *defaultVal : TQPoint(0,0);
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      TQString s = i->second;
      point = TQPoint( num(s,0),num(s,1) );
   }

   return point;
}

bool ValueMap::readBoolEntry(const TQString& k, bool bDefault )
{
   bool b = bDefault;
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      TQString s = i->second;
      b = (bool)num(s,0);
   }

   return b;
}

int ValueMap::readNumEntry(const TQString& k, int iDefault )
{
   int ival = iDefault;
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      TQString s = i->second;
      ival = num(s,0);
   }

   return ival;
}

TQString ValueMap::readEntry(const TQString& k, const TQString& sDefault )
{
   TQString sval = sDefault;
   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      sval = i->second;
   }

   return sval;
}

TQStringList ValueMap::readListEntry(const TQString& k, const TQStringList& defaultVal, char separator )
{
   TQStringList strList;

   std::map<TQString,TQString>::iterator i = m_map.find( k );
   if ( i!=m_map.end() )
   {
      strList = safeStringSplit( i->second, separator );
      return strList;
   }
   else
      return defaultVal;
}
