/* -*- 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 "tables-config-section.hpp"

#include "common.hpp"
#include "core/logger.hpp"
#include "core/config-file.hpp"

namespace nfd {

NFD_LOG_INIT("TablesConfigSection");

const size_t TablesConfigSection::DEFAULT_CS_MAX_PACKETS = 65536;

TablesConfigSection::TablesConfigSection(Cs& cs,
                                         Pit& pit,
                                         Fib& fib,
                                         StrategyChoice& strategyChoice,
                                         Measurements& measurements,
                                         NetworkRegionTable& networkRegionTable)
  : m_cs(cs)
  // , m_pit(pit)
  // , m_fib(fib)
  , m_strategyChoice(strategyChoice)
  // , m_measurements(measurements)
  , m_networkRegionTable(networkRegionTable)
  , m_areTablesConfigured(false)
{

}

void
TablesConfigSection::setConfigFile(ConfigFile& configFile)
{
  configFile.addSectionHandler("tables",
                               bind(&TablesConfigSection::processConfig, this, _1, _2, _3));
}


void
TablesConfigSection::ensureTablesAreConfigured()
{
  if (m_areTablesConfigured) {
    return;
  }

  NFD_LOG_INFO("Setting CS max packets to " << DEFAULT_CS_MAX_PACKETS);
  m_cs.setLimit(DEFAULT_CS_MAX_PACKETS);

  m_areTablesConfigured = true;
}

void
TablesConfigSection::processConfig(const ConfigSection& configSection,
                                   bool isDryRun,
                                   const std::string& filename)
{
  // tables
  // {
  //    cs_max_packets 65536
  //
  //    strategy_choice
  //    {
  //        /               /localhost/nfd/strategy/best-route
  //        /localhost      /localhost/nfd/strategy/multicast
  //        /localhost/nfd  /localhost/nfd/strategy/best-route
  //        /ndn/broadcast  /localhost/nfd/strategy/multicast
  //    }
  //
  //    network_region
  //    {
  //       /example/region1
  //       /example/region2
  //    }
  // }

  size_t nCsMaxPackets = DEFAULT_CS_MAX_PACKETS;

  boost::optional<const ConfigSection&> csMaxPacketsNode =
    configSection.get_child_optional("cs_max_packets");

  if (csMaxPacketsNode) {
    boost::optional<size_t> valCsMaxPackets =
      configSection.get_optional<size_t>("cs_max_packets");

    if (!valCsMaxPackets) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid value for option \"cs_max_packets\""
                                              " in \"tables\" section"));
    }

    nCsMaxPackets = *valCsMaxPackets;
  }

  boost::optional<const ConfigSection&> strategyChoiceSection =
    configSection.get_child_optional("strategy_choice");

  if (strategyChoiceSection) {
    processStrategyChoiceSection(*strategyChoiceSection, isDryRun);
  }

  boost::optional<const ConfigSection&> networkRegionSection =
    configSection.get_child_optional("network_region");

  if (networkRegionSection) {
    processNetworkRegionSection(*networkRegionSection, isDryRun);
  }

  if (!isDryRun) {
    NFD_LOG_INFO("Setting CS max packets to " << nCsMaxPackets);

    m_cs.setLimit(nCsMaxPackets);
    m_areTablesConfigured = true;
  }
}

void
TablesConfigSection::processStrategyChoiceSection(const ConfigSection& configSection,
                                                  bool isDryRun)
{
  // strategy_choice
  // {
  //   /               /localhost/nfd/strategy/best-route
  //   /localhost      /localhost/nfd/strategy/multicast
  //   /localhost/nfd  /localhost/nfd/strategy/best-route
  //   /ndn/broadcast  /localhost/nfd/strategy/multicast
  // }

  std::map<Name, Name> choices;

  for (const auto& prefixAndStrategy : configSection) {
    const Name prefix(prefixAndStrategy.first);
    if (choices.find(prefix) != choices.end()) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error("Duplicate strategy choice for prefix \"" +
                                              prefix.toUri() + "\" in \"strategy_choice\" "
                                              "section"));
    }

    const std::string strategyString(prefixAndStrategy.second.get_value<std::string>());
    if (strategyString.empty()) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid strategy choice \"\" for prefix \"" +
                                              prefix.toUri() + "\" in \"strategy_choice\" "
                                              "section"));
    }

    const Name strategyName(strategyString);
    if (!m_strategyChoice.hasStrategy(strategyName)) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error("Invalid strategy choice \"" +
                                              strategyName.toUri() + "\" for prefix \"" +
                                              prefix.toUri() + "\" in \"strategy_choice\" "
                                              "section"));
    }

    choices[prefix] = strategyName;
  }


  for (const auto& prefixAndStrategy : choices) {
    if (!isDryRun && !m_strategyChoice.insert(prefixAndStrategy.first, prefixAndStrategy.second)) {
      BOOST_THROW_EXCEPTION(ConfigFile::Error("Failed to set strategy \"" +
                                              prefixAndStrategy.second.toUri() + "\" for "
                                              "prefix \"" + prefixAndStrategy.first.toUri() +
                                              "\" in \"strategy_choicev\""));
    }
  }
}

void
TablesConfigSection::processNetworkRegionSection(const ConfigSection& configSection,
                                                 bool isDryRun)
{
  // network_region
  // {
  //    /example/region1
  //    /example/region2
  // }

  if (!isDryRun) {
    m_networkRegionTable.clear();
  }

  for (const auto& pair : configSection) {
    const Name region(pair.first);

    if (!isDryRun)  {
      m_networkRegionTable.insert(region);
    }
  }
}


} // namespace nfd
