#ifndef Morpheo_Debug_h
#define Morpheo_Debug_h

/*
 * $Id: Debug.h 97 2008-12-19 15:34:00Z rosiere $
 *
 * [ Description ]
 * 
 * function to help the debugging :
 *
 *  - log_printf
 *  - log_begin
 *  - log_end
 *  - log_function
 *  - msg_print
 *  - breakpoint
 *
 *  Debug's Level :
 *  - None    : print elementary information
 *  - Info    : print basic information
 *  - Trace   : trace internal variable
 *  - Func    : trace call and return function
 *  - All     : print all information
 */

#include "Common/include/Message.h"
#include "Common/include/FromString.h"
#include "Common/include/ChangeCase.h"
#include "Behavioural/include/Debug_component.h"
#include <systemc.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <string>

namespace morpheo {

typedef enum 
  {
    DEBUG_NONE ,
    DEBUG_INFO ,
    DEBUG_TRACE,
    DEBUG_FUNC ,
    DEBUG_ALL
  } debug_verbosity_t;

  extern debug_verbosity_t debug;

void        debug_init    (void);
void        debug_init    (debug_verbosity_t level);
#ifdef DEBUG

# define log_printf(level, component, func, str... )			\
  do									\
    {									\
      debug_init();                                                     \
                                                                        \
      if ((debug == DEBUG_ALL ) or					\
	  (DEBUG_ ## level == DEBUG_NONE) or				\
	  (( DEBUG_ ## level     <= debug) and				\
	   ( DEBUG_ ## component == true )) )				\
	{								\
	  if (DEBUG_ ## level <= DEBUG_INFO)				\
	    {								\
              msg("%s ",MSG_INFORMATION);                               \
	    }								\
          else                                                          \
	    {								\
              msg("%s ",MSG_DEBUG);                                     \
	    }								\
                                                                        \
	  if (debug >= DEBUG_ALL )					\
	    {								\
	      switch (DEBUG_ ## level)					\
		{							\
		case DEBUG_NONE  : msg(_("(none       ) ")); break;	\
		case DEBUG_INFO  : msg(_("(information) ")); break;	\
		case DEBUG_TRACE : msg(_("(trace      ) ")); break;	\
		case DEBUG_FUNC  : msg(_("(function   ) ")); break;	\
		case DEBUG_ALL   : msg(_("(all        ) ")); break;	\
		default          : msg(_("(undefine   ) ")); break;	\
		}							\
	    }								\
	  if (debug >= DEBUG_FUNC)					\
	    {								\
	      msg(  "<%s> " ,func);			        	\
	      msg(_("In file %s, "),__FILE__);		        	\
	      msg(_("at line %d " ),__LINE__);		        	\
	      msg(  ": " );				        	\
	    }						        	\
	  msg(str);					        	\
	  msg("\n");					        	\
	}								\
    } while(0)

# define log_begin(component, func)					\
  do									\
    {									\
      log_printf(FUNC,component,func,_("Begin"));                       \
    } while(0)

# define log_end(component, func)					\
  do									\
    {									\
      log_printf(FUNC,component,func,_("End"));				\
    } while(0)

#else
# define log_printf(level, component, func, str... )			\
  do									\
    {									\
    } while(0)

# define log_begin(component, func)					\
  do									\
    {									\
    } while(0)

# define log_end(component, func)					\
  do									\
    {									\
    } while(0)

#endif // DEBUG

# define log_function(component,func,name)                              \
  do									\
    {									\
      log_printf(TRACE,component,func,_("[%d] %s.%s"),static_cast<uint32_t>(sc_simulation_time()),name,func); \
    } while(0)


#define msg_printf(type,str...)                                         \
  do                                                                    \
    {                                                                   \
      msg("%s ",MSG_ ## type);                                          \
      msg(str);								\
      msg("\n");							\
    } while(0)


#define breakpoint(str...)						\
  do									\
    {									\
      fprintf(stdout,_("%s "),MSG_BREAKPOINT);                                     \
      fprintf(stdout,_("Breakpoint in file %s, line %d.\n"),__FILE__,__LINE__);    \
      fprintf(stdout,_("%s "),MSG_NONE);                                           \
      fprintf(stdout,str);								\
      fprintf(stdout,_("\n"));                                                     \
      fprintf(stdout,_("%s "),MSG_NONE);                                           \
      fprintf(stdout,_("Enter any key to continue\n"));                            \
      getchar();							\
    } while(0)

#ifdef DEBUG_TEST
#define TEST_PTR(x)							\
  do									\
    {									\
      if (x == NULL)							\
	err(_("File %s, Line %d, this pointeur is null\n"),__FILE__,__LINE__); \
    }									\
  while (0)
#else
#define TEST_PTR(x)	 \
  do			 \
    {			 \
    }			 \
  while (0)
#endif


  template<> inline debug_verbosity_t fromString<debug_verbosity_t> (const std::string& x)
  {
    std::string y=x;
    LowerCase(y);

    if ( (y.compare("0")     == 0) or
         (y.compare("none")  == 0))
      return DEBUG_NONE ;
    if ( (y.compare("1")     == 0) or
         (y.compare("info")  == 0))
      return DEBUG_INFO ;
    if ( (y.compare("2")     == 0) or
         (y.compare("trace") == 0))
      return DEBUG_TRACE;
    if ( (y.compare("3")     == 0) or
         (y.compare("func")  == 0))
      return DEBUG_FUNC ;
    if ( (y.compare("4")     == 0) or
         (y.compare("all")   == 0))
      return DEBUG_ALL  ;

#ifdef DEBUG
    return DEBUG;
#else
    return DEBUG_NONE ;
#endif
  }

}; // end namespace morpheo
#endif // !DEBUG_H
