/***************************************************************************
 *   Copyright (C) 2005 by Joris Guisson                                   *
 *   joris.guisson@gmail.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.             *
 ***************************************************************************/

#ifndef JORISLOG_H
#define JORISLOG_H


#include "constants.h"
#include <QUrl>
#include <QString>
#include <ktorrent_export.h>

// LOG MESSAGES CONSTANTS
#define LOG_NONE 0x00
#define LOG_IMPORTANT 0x01
#define LOG_NOTICE 0x03
#define LOG_DEBUG 0x07
#define LOG_ALL 0x0F

#define SYS_GEN 0x0010 // Genereral info messages
#define SYS_CON 0x0020 // Connections
#define SYS_TRK 0x0040 // Tracker
#define SYS_DHT 0x0080 // DHT
#define SYS_DIO 0x0100 // Disk IO related stuff, saving and loading of chunks ...
#define SYS_UTP 0x0200 // UTP

//plugins
#define SYS_IPF 0x1000  // IPFilter
#define SYS_SRC 0x2000  // Search plugin
#define SYS_PNP 0x4000  // UPnP plugin
#define SYS_INW 0x8000  // InfoWidget
#define SYS_SNF 0x10000 // ScanFolder plugin
#define SYS_MPL 0x20000 // Media player plugin
#define SYS_SCD 0x40000 // Scheduler plugin
#define SYS_BTF 0x80000 // BitFinder plugin
#define SYS_WEB 0x100000 // WebInterface plugin
#define SYS_ZCO 0x200000 // ZeroConf plugin
#define SYS_SCR 0x400000 // Scripting plugin
#define SYS_SYN 0x800000 // Syndication plugin


namespace bt
{
class LogMonitorInterface;

/**
* @author Joris Guisson
* @brief Class which writes messages to a logfile
*
* This class writes messages to a logfile. To use it, create an instance,
* set the output file and write stuff with the << operator.
*
* By default all messages will also be printed on the standard output. This
* can be turned down using the @a setOutputToConsole function.
*
* There is also the possibility to monitor what is written to the log using
* the LogMonitorInterface class.
*/
class KTORRENT_EXPORT Log
{
    class Private;

    Private* priv;
public:
    /**
    * Constructor.
    */
    Log();

    /**
    * Destructor, closes the file.
    */
    virtual ~Log();

    /**
    * Enable or disable the printing of log messages to the standard
    * output.
    * @param on Enable or disable
    */
    void setOutputToConsole(bool on);

    /**
     * Add a log monitor.
     * @param m The log monitor
     */
    void addMonitor(LogMonitorInterface* m);

    /**
     * Remove a log monitor. It will not be deleted.
     * @param m The log monitor
     */
    void removeMonitor(LogMonitorInterface* m);

    /**
    * Set the output logfile.
    * @param file The name of the file
    * @param rotate Whether or not to rotate the logs
    * @param bool handle_qt_messages Whether or not handle Qt messages
    * @throw Exception if the file can't be opened
    */
    void setOutputFile(const QString & file, bool rotate, bool handle_qt_messages);

    /**
    * Write a number to the log file.
    * Anything which can be passed to QString::number will do.
    * @param val The value
    * @return This Log
    */
    template <class T>
    Log & operator << (T val)
    {
        return operator << (QString::number(val));
    }

    /**
    * Apply a function to the Log.
    * @param func The function
    * @return This Log
    */
    Log & operator << (Log & (*func)(Log &))
    {
        return func(*this);
    }


    /**
     * Output a QString to the log.
     * @param s The QString
     * @return This Log
     */
    Log & operator << (const char* s);

    /**
     * Output a QString to the log.
     * @param s The QString
     * @return This Log
     */
    Log & operator << (const QString & s);

    /**
     * Output a 64 bit integer to the log.
     * @param v The integer
     * @return This Log
     */
    Log & operator << (Uint64 v);

    /**
     * Output a 64 bit integer to the log.
     * @param v The integer
     * @return This Log
     */
    Log & operator << (Int64 v);

    /**
    * Prints and endline character to the Log and flushes it.
    * @param lg The Log
    * @return @a lg
    */
    KTORRENT_EXPORT friend Log & endl(Log & lg);

    /**
     * Write an URL to the file.
     * @param text The QUrl
     * @return This Log
     */
    Log & operator << (const QUrl & url);

    /**
     * Sets a filter for log messages. Applies only to listeners via LogMonitorInterface!
     * @param filter SYS & LOG flags combined with bitwise OR.
     */
    void setFilter(unsigned int filter);

    /// Lock the mutex of the log, should be called in Out()
    void lock();

    /// Called by the auto log rotate job when it has finished
    void logRotateDone();
};

KTORRENT_EXPORT Log & endl(Log & lg);
KTORRENT_EXPORT Log & Out(unsigned int arg = 0x00);


/**
 * Initialize the global log.
 * @param file The log file
 * @param rotate_logs Set to true if the logs need to be rotated
 * @param handle_qt_messages Set to true if Qt messages need to be logged
 * @param to_stdout Set to true if output to standard output is required
 * */
KTORRENT_EXPORT void InitLog(const QString & file, bool rotate_logs = false, bool handle_qt_messages = true, bool to_stdout = false);

/// Add a monitor to the global log
KTORRENT_EXPORT void AddLogMonitor(LogMonitorInterface* m);

/// Remove a monitor from the global log
KTORRENT_EXPORT void RemoveLogMonitor(LogMonitorInterface* m);
}

#endif
