/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2016,  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 <ndn-cxx/util/logging.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;

  // Let ndn-cxx logging facility initialize Boost.Log backend,
  // so that only one sink is attached to Boost.Log core.
  ndn::util::Logging::setDestination(std::clog);
}

LoggerFactory::~LoggerFactory()
{
  ndn::util::Logging::flush();
}

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);
  }
}

void
LoggerFactory::flushBackend()
{
  ndn::util::Logging::flush();
}

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
