#ifndef IMLOG_HH_
#define IMLOG_HH_
#include <stdarg.h>
#include <stdio.h>
#include "basictype.hh"

class IMLog;

/* singleton class */
class IMLog
{
  public:
    enum LOG_LEVEL {
	    INVALID = -1,
	    QUIET,
	    ERROR,
	    WARNING,
	    NORMAL,
	    INFO,
	    VERBOSE,
	    DEBUGLOG
    };
    enum LOG_DESTINATION {
	    IMLOG_DEFAULT = -1,
	    IMLOG_STDOUT,
	    IMLOG_STDERR,
	    SYSLOG_AUTHPRIV,
	    SYSLOG_USER,
	    SYSLOG_LOCAL0,
	    SYSLOG_LOCAL1,
	    SYSLOG_LOCAL2,
	    SYSLOG_LOCAL3,
	    SYSLOG_LOCAL4,
	    SYSLOG_LOCAL5,
	    SYSLOG_LOCAL6,
	    SYSLOG_LOCAL7
    };

  private:
    static IMLog *plinst;
    enum LOG_LEVEL lv;
    enum LOG_DESTINATION dest;
    char *progname;

    void output_file(
	FILE *file,
	const char *mes
    );
    void output_syslog(
	int facility,
	int priority,
	const char *mes
    );
    int get_syslog_priority(
	enum LOG_LEVEL l
    );

    virtual void output(
	const char *mes,
	enum LOG_LEVEL lv = NORMAL,
	enum LOG_DESTINATION d = IMLOG_DEFAULT
    );

    IMLog(
	const char *progname
    );
    virtual ~IMLog();
  public:
    static IMLog* get_instance()
    { return plinst; }
    static IMLog* construct(
	const char* progname,
	enum LOG_LEVEL lv = NORMAL,
	enum LOG_DESTINATION d = IMLOG_DEFAULT
    );
    static void cleanup() 
    { 
	if (plinst) delete plinst;
	plinst = NULL;
    }

    bool check(
	enum LOG_LEVEL l
    ) { return (l <= lv); }
    void voutput(
	enum LOG_LEVEL lv,
	enum LOG_DESTINATION d,
	const char *fmt,
	va_list args
    );
    void set_log_level(
	enum LOG_LEVEL l
    ) { lv = l; }
    void set_default_destination(
	enum LOG_DESTINATION d
    ) { dest = d; }
};

inline void
IMLog_output(
    enum IMLog::LOG_LEVEL lv,
    enum IMLog::LOG_DESTINATION d,
    const char *fmt,
    ...
)
{
    va_list va;
    IMLog *pimlog = IMLog::get_instance();

    if (!(pimlog->check(lv))) return;
    va_start(va, fmt);
    pimlog->voutput(lv, d, fmt, va);
    va_end(va);
}

#define IMLOG_DEFINE_FUNC(fn, lv, sl) \
inline void fn(const char *fmt, ...) \
{ \
    va_list va; \
    IMLog *pimlog = IMLog::get_instance(); \
\
    if (!(pimlog->check(lv))) return; \
    va_start(va, fmt); \
    pimlog->voutput((lv), IMLog::IMLOG_DEFAULT, fmt, va); \
    if (sl != IMLog::IMLOG_DEFAULT) pimlog->voutput((lv), (sl), fmt, va); \
    va_end(va); \
}

IMLOG_DEFINE_FUNC(LOG_CRITICAL, IMLog::ERROR, IMLog::SYSLOG_USER);
IMLOG_DEFINE_FUNC(LOG_ERROR, IMLog::ERROR, IMLog::IMLOG_DEFAULT);
IMLOG_DEFINE_FUNC(LOG_WARNING, IMLog::WARNING, IMLog::IMLOG_DEFAULT);
IMLOG_DEFINE_FUNC(LOG_NORMAL, IMLog::NORMAL, IMLog::IMLOG_DEFAULT);
IMLOG_DEFINE_FUNC(LOG_INFO, IMLog::INFO, IMLog::IMLOG_DEFAULT);
IMLOG_DEFINE_FUNC(LOG_VERBOSE, IMLog::VERBOSE, IMLog::IMLOG_DEFAULT);
IMLOG_DEFINE_FUNC(LOG_DEBUG, IMLog::DEBUGLOG, IMLog::IMLOG_DEFAULT);

#endif /* not IMLOG_HH_ */

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
