/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2015,  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,
 *                           The University of Memphis.
 *
 * 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"

#include <boost/range/adaptor/map.hpp>

#ifdef HAVE_CUSTOM_LOGGER
#error "This file should not be compiled when custom logger is used"
#endif

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 ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
         levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
        levelNo == LOG_ALL) {
      return static_cast<LogLevel>(levelNo);
    }
  }
  catch (const boost::bad_lexical_cast& error) {
  }

  BOOST_THROW_EXCEPTION(LoggerFactory::Error("Unsupported logging level \"" + level + "\""));
}

LogLevel
LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
{
  std::string levelString;
  try {
    levelString = item.get_value<std::string>();
  }
  catch (const boost::property_tree::ptree_error& error) {
  }

  if (levelString.empty()) {
    BOOST_THROW_EXCEPTION(LoggerFactory::Error("No logging level found for option \"" + key + "\""));
  }

  return parseLevel(levelString);
}

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
// }

  if (!isDryRun) {
    ConfigSection::const_assoc_iterator item = section.find("default_level");
    if (item != section.not_found()) {
      LogLevel level = extractLevel(item->second, "default_level");
      setDefaultLevel(level);
    }
    else {
      setDefaultLevel(LOG_INFO);
    }
  }

  for (const auto& i : section) {
    LogLevel level = extractLevel(i.second, i.first);

    if (i.first == "default_level") {
      // do nothing
    }
    else {
      std::unique_lock<std::mutex> lock(m_loggersGuard);
      LoggerMap::iterator loggerIt = m_loggers.find(i.first);
      if (loggerIt == m_loggers.end()) {
        lock.unlock();
        NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
                      i.first << "\" (module not found)");
      }
      else if (!isDryRun) {
        loggerIt->second.setLogLevel(level);
        lock.unlock();
        NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
      }
    }
  }
}

void
LoggerFactory::setDefaultLevel(LogLevel level)
{
  // std::cerr << "changing to default_level " << level << std::endl;
  std::lock_guard<std::mutex> lock(m_loggersGuard);

  m_defaultLevel = level;
  for (auto&& logger : m_loggers) {
    // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
    logger.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::lock_guard<std::mutex> lock(m_loggersGuard);

  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::lock_guard<std::mutex> lock(m_loggersGuard);

  std::list<std::string> modules;
  for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
    modules.push_back(loggerName);
  }

  return modules;
}

} // namespace nfd
