
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */

// openpluginlib - A plugin interface to openlibraries.

// Copyright (C) 2005-2006 Editopia Inc.
// Released under the LGPL.
// For more information, see http://www.openlibraries.org.

#include <openpluginlib/pl/log.hpp>

// std
#include <iostream>
#include <map>

namespace olib { namespace openpluginlib {

template<typename _CharT, typename _Traits = std::char_traits< _CharT > >
class basic_nullOStream
    : virtual public std::basic_ostream<_CharT, _Traits>
{
public:
    explicit basic_nullOStream() : std::basic_ostream<_CharT, _Traits>(NULL) {}
};

typedef basic_nullOStream< char > nullOStream;
typedef basic_nullOStream< wchar_t > wnullOStream;

static nullOStream null_ostream;

Log Log::Debug( int level, const std::string& preamble )
{
    return Log( LOG_DEBUG, level, preamble );
}

Log Log::Warning( const std::string& preamble )
{
    return Log( LOG_WARNING, 2, preamble );
}

Log Log::Critical( const std::string& preamble )
{
    return Log( LOG_CRITICAL, 1, preamble );
}

typedef std::map< Log::LogType, std::ostream* > OutputMap;

OutputMap& getOutputMap()
{
    static OutputMap static_map;
    if ( static_map.empty() )
    {
	static_map[ Log::LOG_DEBUG ] = &std::cout;
	static_map[ Log::LOG_WARNING ] = &std::cerr;
	static_map[ Log::LOG_CRITICAL ] = &std::cerr;
    }

    return static_map;
}

int& getDebugLevel()
{
    static int static_level = 3;
    return static_level;
}

Log::Log( LogType t, int level, const std::string& preamble )
    : type_( t ),
      os_( getOutputMap()[ t ] )
{
    if ( level <= getDebugLevel() )
	*os_ << preamble;
    else
	os_ = &null_ostream;
}

Log::Log( const Log& rhs )
{
    type_ = rhs.type_;
    os_ = rhs.os_;
}

Log::~Log()
{
    *os_ << "\n";
}

void Log::setDestination( LogType t, std::ostream& os )
{
    getOutputMap()[ t ] = &os;
}

void Log::setDestination( std::ostream& os )
{
    setDestination( LOG_DEBUG, os );
    setDestination( LOG_WARNING, os );
    setDestination( LOG_CRITICAL, os );
}

void Log::setLogLevel( int i )
{
    getDebugLevel() = i;
}

std::ostream& Log::operator<<( const std::string& s )
{
    *os_ << s;
    return *os_;
}

} }
