/* -*- 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::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
