/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


#ifndef DDBASEOBJECT_H
#define DDBASEOBJECT_H


#include <ddstring.h>
#include <ddlogmanager.h>
#include <dddefines.h>
#include <iostream>
#include <map>
#include <vector>
#include <stdexcept>

#include <errno.h>
#include <unistd.h>
#include <stdio.h>


using namespace std;

enum dd_result
{
 	rs_error=-1,
 	rs_retry=0,
 	rs_ok=1,
 	rs_redirect=2
};

/// ddbaseobject ist die allgemeine Basisklasse für die meisten dd-Klassen
/**
	Die Idee ist von Java geklaut: ddbaseobjects können string von sich selbst erzeugen
	und nachrichten in log-system schreiben.
*/


class ddbaseobject
{

public:

	virtual ~ddbaseobject()
	{
	
	}
	
	static const char* dd_logtext[];

	virtual ddstring to_string() const;
	virtual void dump() const;

	static  void log_message( int loglevel, const ddstring& message );
	
	virtual bool log_debug( const ddstring& message ) const;
	virtual bool log_error( const ddstring& message ) const;	
	virtual void log_fatal( const ddstring& message ) const;	
	
protected:

	static ddlogmanager thelog;
	
};


/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


/// ddbasestate: Statusinfos, gespeichert in Bitfeldern.
/**
	Die Status-Bits können über die Memberfunktionen set_flag, clear_flag
	and test_flag getestet und manipuliert werden.<br>
	@see ddbasestateobject
*/

class ddbasestate
{

public:

	ddbasestate();


	/**
  	Setze das gesamte Bitfeld.
  	@param state das neue bitfield.
  */

  inline void set_state_flags( int state )
  {
  	_flags = state;
  }


  /**
  	Setzt ein Flag. Alle 1-bits des Parameters werden gesetzt.
  	(Es wird ver-ODER-t)
  	@param flag the flag to set.
  */

  inline void set_flag( int flag )
  {
  	_flags |= flag;
  }


  /**
  	Setzt ein Flag auf 'newstat'
  	@param flag das Flag
  	@param newatate  der neue Zustand.
  */

  inline void set_flag( int flag, bool newstate )
  {
  	if( newstate )
  		_flags |= flag;
  	else
  		_flags &= ~flag;
  }


  /**
  	Löscht das angegebenen Flag. Alle 1-bits des Parameters 
  	werden gelöscht. (Es wird mit der Negation ver-UND-et)
  	@param flag the flag to clear.
  */

  inline void clear_flag( int flag )
  {
  	_flags &= ~flag;
  }


  /**
  	Testes ein Flag.
  	@param flag Das Flag.
  */

  inline bool test_flag( int flag ) const
  {
  	return ( (_flags & flag) != 0 );
  }

	/**
  	@Returns das gesamte Bitfeld.
  */

  inline size_t get_state_flags() const
  {
  	return _flags;
  }
	
	// FIX! Toggle-Flag fehlt.
	
protected:

	int _flags;

};
	

/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


/// ddbasename ist die Basis für alles was einen Namen hat.
/**
	ddbasename ist die Basis für alles was einen Namen hat, das modelliert 
	per Mehrfachvererbung sozusagen den Namensaspekt eines Objects.
*/


class ddbasename
{

public:

	ddbasename();
	ddbasename( const ddstring& name );
	virtual ~ddbasename()
	{
	}


	/**
  	Returns the name.
  */

  inline const ddstring& get_name() const
  {
  	return _name;
  }

  
	/**
  	Returns the name.
  */

  inline ddstring& get_name()
  {
		return _name;
  }


	/**
  	Sets the name.
  	@param the new name.
  */

  virtual void set_name( const ddstring& name )
  {
  	_name = name;
  }

  
protected:

	ddstring _name;

};


/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


/// ddbasenamedobject is an ddbaseobject with a name.
/**
 @see ddbaseobject
 @see ddbasestate
*/

class ddbasenamedobject : public ddbaseobject, public ddbasename
{

public:

	ddbasenamedobject();
	ddbasenamedobject( const ddstring& name );
	virtual ~ddbasenamedobject();

};


/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


/// ddmapindex :Ein simpler Index, der string auf array-indices mapt.
/**
	ddmapindex wird von etlichen Klassen verwendet, um einen Acces-by-Key
	zu realisieren, also um für einen gegebenen Schlüssel die Array-Position
	in einem vector rauszufinden.
*/

class ddmapindex : public map<ddstring,int>, public ddbaseobject
{

public:

	/**
   	Destructor.Tut nix.     
	*/
	
  virtual ~ddmapindex()
  {
	}


  /**
		Bastelt einen String aus allen Einträgen zum anschauen.
		@see ddbaseobject
	*/
	
  ddstring to_string() const
  {
    ddstring result = "ddmapindex: ";
    ddmapindex::const_iterator pos = begin();
    for( ; pos != end(); ++pos )
    {
      result += (*pos).first;
      result += " -- ";
      result += ddstrutil::from_size_t( (*pos).second );
      result += "; ";
    }
    return result;
  }

  
	/**
		@return 'true' wenn ein Eintrag für 'key' existiert.
	*/

	bool contains_key( const ddstring& key ) const
	{
		return ( find( key ) != end() );
	}
	
	/**
		Einen Key-Index paar einfügen.
	*/
	
	void add_key( const ddstring& key, size_t index )
  {
  	(*this)[key] = index;
  }
  
	/**
		@return die index-position für 'key' oder -1.
	*/

	int index_of( const ddstring& key ) const
	{
		ddmapindex::const_iterator pos = find( key );
		if( pos != end() )
			return (int) (*pos).second;
		return -1;
	}

	
	/**
		Schreibt alle Einträge nach cout.
		@see ddbaseobject
	*/

	void dump() const
	{
		ddmapindex::const_iterator pos = begin();
		for( ; pos != end(); ++pos )
		{
			ddstring line =  "key: <" + (*pos).first + "> value: <" + ddstrutil::from_size_t( (*pos).second ) + ">";
			cout << line << endl;
		}
	}
	
	
	/**
		Baut den index neu auf, nachdem der Eintrag an der Stelle 'index'
		gelöscht wurde.
	*/
	
	void update( size_t index )
	{
		
		ddmapindex newindex;
		ddmapindex::const_iterator pos = begin();
  	for( ; pos != end(); ++pos )
  	{
			
			// item idx == lösch-index: weiter
			// item idx <  lösch-index: eintragen
			// item idx >  lösch-index: decrement & eintragen

			size_t idx = (*pos).second;
			if( idx == index )
				continue;
			if( idx > index )
				idx--;	
      // schlüssel auch sichern
			newindex[(*pos).first] = idx;
		}
	
		swap( newindex );
	
	}

};


#endif
