/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2011-2015  Regents of the University of California.
 *
 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
 * contributors.
 *
 * ndnSIM 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.
 *
 * ndnSIM 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
 * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "ndn-scenario-helper.hpp"
#include "ndn-fib-helper.hpp"
#include "ndn-app-helper.hpp"

#include "ns3/ndnSIM/model/ndn-l3-protocol.hpp"

#include "ns3/names.h"
#include "ns3/point-to-point-helper.h"
#include "ns3/string.h"

namespace ns3 {
namespace ndn {

ScenarioHelper::ScenarioHelper()
  : m_isTopologyInitialized(false)
{
}

void
ScenarioHelper::createTopology(std::initializer_list<std::initializer_list<std::string>/*node clique*/> topology,
                               bool shouldInstallNdnStack)
{
  if (m_isTopologyInitialized) {
    throw std::logic_error("Topology cannot be created twice");
  }

  PointToPointHelper p2p;

  for (auto&& clique : topology) {
    for (auto i = clique.begin(); i != clique.end(); ++i) {
      auto node1 = getOrCreateNode(*i);
      for (auto j = i + 1; j != clique.end(); ++j) {
        auto node2 = getOrCreateNode(*j);

        auto link = p2p.Install(node1, node2);
        links[*i][*j] = link.Get(0);
        links[*j][*i] = link.Get(1);
      }
    }
  }

  if (shouldInstallNdnStack) {
    ndnHelper.InstallAll();
  }
  m_isTopologyInitialized = true;
}

void
ScenarioHelper::disableRibManager()
{
  ndnHelper.disableRibManager();
}

// void
// ScenarioHelper::disableFaceManager()
// {
//   ndnHelper.disableFaceManager();
// }

void
ScenarioHelper::disableStrategyChoiceManager()
{
  ndnHelper.disableStrategyChoiceManager();
}

void
ScenarioHelper::disableForwarderStatusManager()
{
  ndnHelper.disableForwarderStatusManager();
}

void
ScenarioHelper::addRoutes(std::initializer_list<ScenarioHelper::RouteInfo> routes)
{
  for (auto&& route : routes) {
    FibHelper::AddRoute(getNode(route.node1), route.prefix,
                        getFace(route.node1, route.node2), route.metric);
  }
}

void
ScenarioHelper::addApps(std::initializer_list<ScenarioHelper::AppInfo> apps)
{
  for (auto&& app : apps) {
    AppHelper appHelper(app.name);
    for (auto&& param : app.params) {
      appHelper.SetAttribute(param.first, StringValue(param.second));
    }
    auto installedApp = appHelper.Install(getNode(app.node));
    installedApp.Start(Time(app.start));
    installedApp.Stop(Time(app.end));
  }
}

Ptr<Node>
ScenarioHelper::getOrCreateNode(const std::string& nodeName)
{
  auto node = nodes.find(nodeName);
  if (node == nodes.end()) {
    std::tie(node, std::ignore) = nodes.insert(std::make_pair(nodeName, CreateObject<Node>()));
    Names::Add(nodeName, node->second);
  }
  return node->second;
}

Ptr<Node>
ScenarioHelper::getNode(const std::string& nodeName)
{
  auto node = nodes.find(nodeName);
  if (node != nodes.end()) {
    return node->second;
  }

  throw std::invalid_argument("Node " + nodeName + " does not exist");
}

shared_ptr<Face>
ScenarioHelper::getFace(const std::string& node1, const std::string& node2)
{
  Ptr<NetDevice> netDevice = getNetDevice(node1, node2);
  return netDevice->GetNode()->GetObject<L3Protocol>()->getFaceByNetDevice(netDevice);
}

Ptr<NetDevice>
ScenarioHelper::getNetDevice(const std::string& node1, const std::string& node2)
{
  auto i = links.find(node1);
  if (i != links.end()) {
    auto j = i->second.find(node2);
    if (j != i->second.end()) {
      return j->second;
    }
  }

  throw std::invalid_argument("Link between " + node1 + " and " + node2 + " does not exist");
}

StackHelper&
ScenarioHelper::getStackHelper()
{
  return ndnHelper;
}

} // namespace ndn
} // namespace ns3
