/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014  Regents of the University of California,
 *                     Arizona Board of Regents,
 *                     Colorado State University,
 *                     University Pierre & Marie Curie, Sorbonne University,
 *                     Washington University in St. Louis,
 *                     Beijing Institute of Technology
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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 3 of the License, or (at your option) any later version.
 *
 * NFD 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
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "logger-factory.hpp"

namespace nfd {

NFD_LOG_INIT("LoggerFactory");

LoggerFactory&
LoggerFactory::getInstance()
{
  static LoggerFactory globalLoggerFactory;

  return globalLoggerFactory;
}

LoggerFactory::LoggerFactory()
  : m_defaultLevel(LOG_INFO)
{
  m_levelNames["NONE"] = LOG_NONE;
  m_levelNames["ERROR"] = LOG_ERROR;
  m_levelNames["WARN"] = LOG_WARN;
  m_levelNames["INFO"] = LOG_INFO;
  m_levelNames["DEBUG"] = LOG_DEBUG;
  m_levelNames["TRACE"] = LOG_TRACE;
  m_levelNames["ALL"] = LOG_ALL;
}

void
LoggerFactory::setConfigFile(ConfigFile& config)
{
  config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
}

LogLevel
LoggerFactory::parseLevel(const std::string& level)
{
  std::string upperLevel = level;
  boost::to_upper(upperLevel);

  // std::cerr << "parsing level: " << upperLevel << std::endl;;
  // std::cerr << "# levels: " << m_levelNames.size() << std::endl;
  // std::cerr << m_levelNames.begin()->first << std::endl;

  LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
  if (levelIt != m_levelNames.end())
    {
      return levelIt->second;
    }
  try
    {
      uint32_t levelNo = boost::lexical_cast<uint32_t>(level);

      if ((LOG_NONE <= levelNo && levelNo <= LOG_TRACE) ||
          levelNo == LOG_ALL)
        {
          return static_cast<LogLevel>(levelNo);
        }
    }
  catch (const boost::bad_lexical_cast& error)
    {
    }
  throw LoggerFactory::Error("Unsupported logging level \"" +
                             level + "\"");
}


void
LoggerFactory::onConfig(const ConfigSection& section,
                        bool isDryRun,
                        const std::string& filename)
{
// log
// {
//   ; default_level specifies the logging level for modules
//   ; that are not explicitly named. All debugging levels
//   ; listed above the selected value are enabled.
//
//   default_level INFO
//
//   ; You may also override the default for specific modules:
//
//   FibManager DEBUG
//   Forwarder WARN
// }

  // std::cerr << "loading logging configuration" << std::endl;
  for (ConfigSection::const_iterator item = section.begin();
       item != section.end();
       ++item)
    {
      std::string levelString;
      try
        {
          levelString = item->second.get_value<std::string>();
        }
      catch (const boost::property_tree::ptree_error& error)
        {
        }

      if (levelString.empty())
        {
          throw LoggerFactory::Error("No logging level found for option \"" + item->first + "\"");
        }

      LogLevel level = parseLevel(levelString);

      if (item->first == "default_level")
        {
          if (!isDryRun)
            {
              setDefaultLevel(level);
            }
        }
      else
        {
          LoggerMap::iterator loggerIt = m_loggers.find(item->first);
          if (loggerIt == m_loggers.end())
            {
              NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
                            item->first << "\" (module not found)");
            }
          else if (!isDryRun)
            {
              // std::cerr << "changing level for module " << item->first << " to " << level << std::endl;
              loggerIt->second.setLogLevel(level);
            }
        }
    }
}

void
LoggerFactory::setDefaultLevel(LogLevel level)
{
  // std::cerr << "changing to default_level " << level << std::endl;

  m_defaultLevel = level;
  for (LoggerMap::iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
    {
      // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
      i->second.setLogLevel(m_defaultLevel);
    }
}

Logger&
LoggerFactory::create(const std::string& moduleName)
{
  return LoggerFactory::getInstance().createLogger(moduleName);
}

Logger&
LoggerFactory::createLogger(const std::string& moduleName)
{
  // std::cerr << "creating logger for " << moduleName
  //           << " with level " << m_defaultLevel << std::endl;

  std::pair<LoggerMap::iterator, bool> loggerIt =
    m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));

  return loggerIt.first->second;
}

std::list<std::string>
LoggerFactory::getModules() const
{
  std::list<std::string> modules;
  for (LoggerMap::const_iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
    {
      modules.push_back(i->first);
    }

  return modules;
}

} // namespace nfd
