// Copyright 2005 Rutger E.W. van Beusekom.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef __LOGSTREAM_H_INCLUDED__
#define __LOGSTREAM_H_INCLUDED__

#include <ostream>
#include <streambuf>
#include <vector>

#include <boost/thread/mutex.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class qualifier;

extern qualifier info;
extern qualifier warn;
extern qualifier error;
extern qualifier trace;
extern qualifier debug;


class logstream;

class logger: public boost::noncopyable
{
  static boost::mutex mutex_;
  static std::vector<std::ostream*> output_;
private:
  logger();
  ~logger();
public:
  static void log(const char*);
  static std::ostream& acquire(bool enable = true);
};

class qualifier: public boost::noncopyable
{
  const char* type_;
  bool enabled_;
public:
  qualifier(const char* type);
  virtual ~qualifier();
  void enable() { enabled_ = true; }
  void disable() { enabled_ = false; }
  bool is_enabled() const { return enabled_; }
  operator bool() const { return enabled_;}
protected:
  inline const char* type() const { return type_; }
  unsigned thread_id() const;
  boost::posix_time::time_duration time_stamp() const;
  virtual std::ostream& qualify() const;
private:
  template <typename T>
  inline friend std::ostream& operator << (const qualifier& q, const T& t)
  {
    std::ostream& os = q.qualify();
    os << t;
    return os;
  }
  friend std::ostream& operator << (std::ostream& os, const qualifier& q);
};

class logstream: public boost::noncopyable, public std::ostream
{
  friend class thread_local;
  class logstreambuf: public  std::streambuf
  {
    std::vector<char> buffer_;
  public:
    logstreambuf();
    ~logstreambuf();
    virtual std::streamsize xsputn(const char* p, std::streamsize n);
    virtual int sync();
    virtual int overflow(int);
  private:
    char* begin();
    char* end();
  };
  logstreambuf streambuf_;
private:
  logstream();
  virtual ~logstream();
};

#endif // __LOGSTREAM_H_INCLUDED__
