//-----------------------------------------------------------
// Copyright Christian Arnault LAL-Orsay CNRS
// arnault@lal.in2p3.fr
// See the complete license in cmt_license.txt "http://www.cecill.info". 
//-----------------------------------------------------------

#ifndef __cmt_log_h__
#define __cmt_log_h__

#include "cmt_string.h"

class CmtLogEnd
{
public:
};

class CmtLogDummy
{
public:
};

class CmtLog
{
public:
  CmtLog ();

  static CmtLogEnd& end ();
  CmtLog& operator << (const cmt_string& s);
  CmtLog& operator << (const char* c);
  CmtLog& operator << (int i);
  CmtLog& operator << (double d);
  CmtLog& operator << (void* p);
  CmtLog& operator << (CmtLogEnd& end);
  CmtLog& operator << (CmtLogDummy& dummy);

private:
  bool check ();
};

#define Log static CmtLog log_instance
#define log_endl CmtLog::end ()
#define log      if (Cmt::get_debug ()) log_instance << CmtMessage::prefix () + " (" << __FILE__ << ":" << __LINE__ << ") "
//#define log      if (Cmt::get_debug ()) log_instance << "#CMT> (" << __FILE__ << "-" << __LINE__ << ") "
#define log_cont if (Cmt::get_debug ()) log_instance


enum CmtMsgLevel
  {
    Nil = 0,
    Debug,
    Verbose,
    Info,
    Warning,
    Error,
    Fatal
  };

class CmtMessage
{
public:
  static cmt_string& prefix ();
  static void set_prefix (const cmt_string& prefix);
  static CmtMsgLevel& level ();
  static void set_level (const CmtMsgLevel& level);
  static bool active (const CmtMsgLevel& level);
  static void verbose (const cmt_string& message);
  static void info (const cmt_string& message);
  static void warning (const cmt_string& message);
  static void error (const cmt_string& message);
  static void fatal (const cmt_string& message);

private:
  CmtMessage ();
  static CmtMessage& instance ();
  cmt_string m_prefix;
  CmtMsgLevel m_level;
};

/**----------------------------------------------------------
   The CmtMessage default constructor
   Here are primarily constructed all default definitions
*/
inline CmtMessage::CmtMessage ()
  : m_prefix ("#CMT--->"), m_level (Info)
{ }

/**----------------------------------------------------------
   The CmtMessage singleton
*/
inline CmtMessage& CmtMessage::instance ()
{
  static CmtMessage me;
  return me;
}

inline cmt_string& CmtMessage::prefix ()
{
  return instance ().m_prefix;
}

inline void CmtMessage::set_prefix (const cmt_string& prefix)
{
  instance ().m_prefix = prefix;
}

inline CmtMsgLevel& CmtMessage::level ()
{
  return instance ().m_level;
}

inline void CmtMessage::set_level (const CmtMsgLevel& level)
{
  instance ().m_level = level;
}

inline bool CmtMessage::active (const CmtMsgLevel& lvl)
{
  return level () <= lvl;
}

inline void CmtMessage::verbose (const cmt_string& message)
{
  if (active (Verbose))
    cerr << prefix () << " Verbose: " << message << endl;
}

inline void CmtMessage::info (const cmt_string& message)
{
  if (active (Info))
    cerr << prefix () << " Info: " << message << endl;
}

inline void CmtMessage::warning (const cmt_string& message)
{
  if (active (Warning))
    cerr << prefix () << " Warning: " << message << endl;
}

inline void CmtMessage::error (const cmt_string& message)
{
  if (active (Error))
    cerr << prefix () << " Error: " << message << endl;
}

inline void CmtMessage::fatal (const cmt_string& message)
{
  if (active (Fatal))
    cerr << prefix () << " Fatal: " << message << endl;
}
#endif
