//  BMP
//  Copyright (C) 2005-2007 BMP development.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License Version 2
//  as published by the Free Software Foundation.
//
//  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//  --
//
//  The BMPx project hereby grants permission for non-GPL compatible GStreamer
//  plugins to be used and distributed together with GStreamer and BMPx. This
//  permission is above and beyond the permissions granted by the GPL license
//  BMPx is covered by.

#define G_LOG_DOMAIN "BMP"

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif //HAVE_CONFIG_H

#include <iostream>
#include <fstream>
#include <ctime>
#include <sys/stat.h>
#include <unistd.h>
#include <cstdio>

#include <glibmm.h>
#include <glib/gstdio.h>
#include <boost/shared_ptr.hpp>
#include <boost/format.hpp>

#include "paths.hh"
#include "logger.hh"


namespace
{
  struct LogHandler
  {
    gchar          *domain;
    gchar          *file;
    GLogLevelFlags  level;
    guint           id;
  };

  const char *plainlog_ext = ".log";

  const LogHandler log_handlers[] =
  {
    {G_LOG_DOMAIN,                    "bmp",      LOG_ALL_LEVELS},
    {"Glib",                          "glib",     LOG_ALL_LEVELS},
    {"Gtk",                           "gtk",      LOG_ALL_LEVELS}
  };

  const guint log_handler_count = G_N_ELEMENTS (log_handlers);

  std::size_t
  get_filesize (const std::string &filename)
  {
    struct stat info;

    if (stat (filename.c_str (), &info))
      return 0;

    return info.st_size;
  }

  Glib::ustring
  get_timestamp_str ()
  {
    std::time_t current_time = std::time (0);

    std::tm current_tm;
    localtime_r (&current_time, &current_tm);

    char buffer[256];
    std::size_t len = std::strftime (buffer, sizeof (buffer) - 1, "%F %T", &current_tm);
    buffer[len] = 0;
    g_strstrip (buffer);

    return Glib::locale_to_utf8 (buffer);
  }

} // anonymous

namespace Bmp
{
  ///////////////////////////////////////////

  Log::Log (Glib::ustring const &domain_,
            const std::string   &filename_,
            GLogLevelFlags       flags)
    : domain (domain_)
  {
    std::string filename = filename_ + std::string(plainlog_ext);

    if (get_filesize (filename) < BMP_LOGGER_FILE_MAX_SIZE)
      logfile.open (filename.c_str(), std::ios::app);
    else
      logfile.open (filename.c_str(), std::ios::out | std::ios::trunc);

    id = g_log_set_handler (domain.c_str(),
                            (GLogLevelFlags) (flags | BMP_LOGGER_DEFAULT_LOG_LEVEL),
                            log_to_file_wrap,
                            this);

    g_log (domain.c_str(), G_LOG_LEVEL_INFO,
           "Logging started for [%s] at [%s], PID[%d]",
           domain.c_str(), get_timestamp_str().c_str (), getpid ());

    // Create XML Log
  }

  Log::~Log ()
  {
    g_log_remove_handler (domain.c_str (), id);
  }

  void
  Log::log_to_file (const char     *domain,
                    GLogLevelFlags  flags,
                    const char     *message)
  {
    Glib::Mutex::Lock locker (file_mutex);

    logfile << get_timestamp_str ();

    if (domain)
      {
        logfile << " " << domain << ": ";
      }

    logfile << (message ? message : "(null)") << "\n";
    logfile.flush();
  }

  void
  Log::log_to_file_wrap (const char     *domain,
                         GLogLevelFlags  flags,
                         const char     *message,
                         void*           data)

  {
    Bmp::Log* log = static_cast<Bmp::Log*> (data);
    log->log_to_file (domain, flags, message);
  }


  Logger::Logger ()
  {
    for (unsigned int i = 0; i < log_handler_count; i++)
      {
        add_log (log_handlers[i].domain,
                 log_handlers[i].file,
                 log_handlers[i].level);
      }
  }

  void
  Logger::add_log (Glib::ustring const &domain,
                   const std::string   &filename,
                   GLogLevelFlags       flags)
  {
    std::string path = Glib::build_filename (BMP_PATH_LOGS_DIR, filename);
    logs[domain] = boost::shared_ptr<Bmp::Log> (new Bmp::Log (domain, path, flags));
  }

} // Bmp
