/*
 *       File name:  common/log-facility.hh
 *         Project:  Aghermann
 *          Author:  Andrei Zavada <johnhommer@gmail.com>
 * Initial version:  2009-06-28 (in aghermann since 2013-09-28)
 *
 *         Purpose:  Simple log facility
 *
 *         License:  GPL
 */

#ifndef AGH_COMMON_LOG_FACILITY_H
#define AGH_COMMON_LOG_FACILITY_H

#include <cstdarg>
#include <fstream>

using namespace std;


namespace agh {
namespace log {

enum TLevel {
        self,  // reserved for log-facility itself
        error = 1, warning, info, debug
};
const char* level_s( TLevel);

class CLogFacility {

    public:
        CLogFacility( const string& log_fname, // "-" means stdout
                      TLevel level_ = TLevel::info, // print messages of level up and including this
                      bool compact_repeated_messages_ = true,
                      unsigned short sec_dec_places = 3);
       ~CLogFacility();

        void msg( TLevel, const char* issuer, const char* fmt, ...) __attribute__ ((format (printf, 4, 5)));
        void vmsg( TLevel, const char* issuer, const char* fmt, va_list);

        TLevel  level;
        bool    compact_repeated_messages:1;

    private:
        string  _log_fname;
        FILE*   _f;
        unsigned short
                sec_dec_places;

        string  _last_line;
        struct timeval
                _last_tp;
        size_t  _repeating_last;
};


struct SLoggingClient {
        agh::log::CLogFacility*
                _log_facility;
        SLoggingClient (agh::log::CLogFacility* log_facility_ = nullptr)
              : _log_facility (log_facility_)
                {}
        void log( agh::log::TLevel, const char* issuer, const char* fmt, ...) __attribute__ ((format (printf, 4, 5)));
};

#define LOG_SOURCE_ISSUER agh::str::sasprintf("%s:%d:", __FILE__, __LINE__).c_str()

#define LOG_DEBUG(...) do this->log( agh::log::TLevel::debug,   LOG_SOURCE_ISSUER, __VA_ARGS__); while (0)
#define LOG_INFO(...)  do this->log( agh::log::TLevel::info,    LOG_SOURCE_ISSUER, __VA_ARGS__); while (0)
#define LOG_WARN(...)  do this->log( agh::log::TLevel::warning, LOG_SOURCE_ISSUER, __VA_ARGS__); while (0)
#define LOG_ERROR(...) do this->log( agh::log::TLevel::error,   LOG_SOURCE_ISSUER, __VA_ARGS__); while (0)

}}  // namespace agh::log

#endif

// Local Variables:
// Mode: c++
// indent-tabs-mode: nil
// tab-width: 8
// c-basic-offset: 8
// End:
