#ifndef Morpheo_Test_h
#define Morpheo_Test_h

/*
 * $Id: Test.h 88 2008-12-10 18:31:39Z rosiere $
 *
 * [ Description ]
 * 
 * Macro / function to test
 */

#include <iostream>
#include <sstream>
#include <stdint.h>
#include "Common/include/Message.h"
#include "Common/include/ErrorMorpheo.h"
#include "Common/include/ToString.h"

namespace morpheo {

#define STR_OK "Test OK"
#define STR_KO "Test KO"

static uint32_t num_test;

inline void test_ko_error (void)
{
  std::string msg = "Test ko : error in test \""+morpheo::toString(num_test)+"\"";
  throw (morpheo::ErrorMorpheo (msg));
}
  
template <class T>
inline void test_ko (char * file, uint32_t line, T exp1, T exp2)
{
  fflush (stdout);
  fflush (stderr);

  std::cerr << "[" << num_test << "] : " << STR_KO
       << "\tline " << line                      << std::endl
       << " * Localisation"                      << std::endl
       << "   - File : " << file                 << std::endl
       << "   - Line : " << line                 << std::endl
       << " * Expression is different"           << std::endl
       << "   - exp1 : "+morpheo::toString(exp1) << std::endl
       << "   - exp2 : "+morpheo::toString(exp2) << std::endl;

  test_ko_error ();
};

inline void test_ko (char * file, uint32_t line)
{
  fflush (stdout);
  fflush (stderr);

  std::cerr << "[" << num_test << "] : " << STR_KO
       << "\tline " << line                           << std::endl
       << " * Localisation"                           << std::endl
       << "   - File : " << file                      << std::endl
       << "   - Line : " << line                      << std::endl;
  
  test_ko_error ();
};

inline void test_ok ()
{
  fflush (stdout);
  fflush (stderr);

  msg (_("[%d] : %s\n"), num_test,STR_OK);

  num_test ++;
};

inline void test_ok (char * file, uint32_t line)
{
  fflush (stdout);
  fflush (stderr);

  msg (_("[%d] : %s\n"), num_test,STR_OK);
  msg (_("\tline %d\n"), line);

  num_test ++;
};

template <class T>
inline void test_ok (char * file, uint32_t line, T exp)
{
  fflush (stdout);
  fflush (stderr);

  msg (_("[%d] : %s\n"), num_test, STR_OK);
  msg (_("\tline %d\n"), line);
  msg (_("\tvalue %s\n"), (morpheo::toString(exp)).c_str());

  num_test ++;
}

template <class T>
inline void test(char * file, uint32_t line, T exp1, T exp2)
{
  if (exp1 != exp2)
    test_ko <T> (file,line,exp1,exp2);
  else
    test_ok <T> (file,line,exp1);
};

#define TEST(type,exp1,exp2)            do {morpheo::test<type> (__FILE__,__LINE__,exp1,exp2);} while(0)
#define TEST_STR(type,exp1,exp2,str...) do {fprintf(stdout,str); fprintf(stdout,"\n"); morpheo::test<type> (__FILE__,__LINE__,exp1,exp2);} while(0)
#define TEST_OK(str...)                 do {fprintf(stdout,str); fprintf(stdout,"\n"); morpheo::test_ok(__FILE__,__LINE__);} while(0)
#define TEST_KO(str...)                 do {fprintf(stdout,str); fprintf(stdout,"\n"); morpheo::test_ko(__FILE__,__LINE__);} while(0)

#define LABEL(str...)							\
  {									\
    msg (_("{%d} "),static_cast<uint32_t>(sc_simulation_time()));	\
    msg (str);								\
    msg (_("\n"));							\
    fflush (stdout);                                                    \
  } while(0)

#ifndef CYCLE_MAX
# error "CYCLE_MAX must be defined";
#endif

#define SC_START(cycle_offset)						\
  do									\
    {									\
      /*cout << "SC_START (begin)" << endl;*/				\
      									\
      uint32_t cycle_current = static_cast<uint32_t>(sc_simulation_time()); \
      if (cycle_offset != 0)						\
	{								\
	  cout << "##########[ cycle "<< cycle_current+cycle_offset << " ] (" << __LINE__ << ")" << endl; \
	}								\
      									\
      if ((CYCLE_MAX != 0) and (cycle_current > CYCLE_MAX))             \
	{								\
	  TEST_KO("Maximal cycles Reached");				\
	}								\
      									\
      sc_start(cycle_offset);						\
      									\
      /*cout << "SC_START (end  )" << endl;*/				\
    } while(0)



};
#endif
