/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022,  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 "rib-module.hpp"
#include "face-module.hpp"
#include "face-helpers.hpp"
#include "format-helpers.hpp"

namespace nfd::tools::nfdc {

void
RibModule::registerCommands(CommandParser& parser)
{
  CommandDefinition defRouteList("route", "list");
  defRouteList
    .setTitle("print RIB routes")
    .addArg("nexthop", ArgValueType::FACE_ID_OR_URI, Required::NO, Positional::YES)
    .addArg("origin", ArgValueType::ROUTE_ORIGIN, Required::NO, Positional::NO);
  parser.addCommand(defRouteList, &RibModule::list);
  parser.addAlias("route", "list", "");

  CommandDefinition defRouteShow("route", "show");
  defRouteShow
    .setTitle("show routes toward a prefix")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES);
  parser.addCommand(defRouteShow, &RibModule::show);

  CommandDefinition defRouteAdd("route", "add");
  defRouteAdd
    .setTitle("add a route")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
    .addArg("nexthop", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES)
    .addArg("origin", ArgValueType::ROUTE_ORIGIN, Required::NO, Positional::NO)
    .addArg("cost", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
    .addArg("no-inherit", ArgValueType::NONE, Required::NO, Positional::NO)
    .addArg("capture", ArgValueType::NONE, Required::NO, Positional::NO)
    .addArg("expires", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
  parser.addCommand(defRouteAdd, &RibModule::add);

  CommandDefinition defRouteRemove("route", "remove");
  defRouteRemove
    .setTitle("remove a route")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
    .addArg("nexthop", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES)
    .addArg("origin", ArgValueType::ROUTE_ORIGIN, Required::NO, Positional::NO);
  parser.addCommand(defRouteRemove, &RibModule::remove);
}

void
RibModule::list(ExecuteContext& ctx)
{
  auto nexthopIt = ctx.args.find("nexthop");
  std::set<uint64_t> nexthops;
  auto origin = ctx.args.getOptional<RouteOrigin>("origin");

  if (nexthopIt != ctx.args.end()) {
    FindFace findFace(ctx);
    FindFace::Code res = findFace.execute(nexthopIt->second, true);

    ctx.exitCode = static_cast<int>(res);
    switch (res) {
      case FindFace::Code::OK:
        break;
      case FindFace::Code::ERROR:
      case FindFace::Code::CANONIZE_ERROR:
      case FindFace::Code::NOT_FOUND:
        ctx.err << findFace.getErrorReason() << '\n';
        return;
      default:
        BOOST_ASSERT_MSG(false, "unexpected FindFace result");
        return;
    }

    nexthops = findFace.getFaceIds();
  }

  listRoutesImpl(ctx, [&] (const RibEntry&, const Route& route) {
    return (nexthops.empty() || nexthops.count(route.getFaceId()) > 0) &&
           (!origin || route.getOrigin() == *origin);
  });
}

void
RibModule::show(ExecuteContext& ctx)
{
  auto prefix = ctx.args.get<Name>("prefix");

  listRoutesImpl(ctx, [&] (const RibEntry& entry, const Route&) {
    return entry.getName() == prefix;
  });
}

void
RibModule::listRoutesImpl(ExecuteContext& ctx, const RoutePredicate& filter)
{
  ctx.controller.fetch<ndn::nfd::RibDataset>(
    [&] (const auto& dataset) {
      bool hasRoute = false;
      for (const RibEntry& entry : dataset) {
        for (const Route& route : entry.getRoutes()) {
          if (filter(entry, route)) {
            hasRoute = true;
            formatRouteText(ctx.out, entry, route, true);
            ctx.out << '\n';
          }
        }
      }

      if (!hasRoute) {
        ctx.exitCode = 6;
        ctx.err << "Route not found\n";
      }
    },
    ctx.makeDatasetFailureHandler("RIB dataset"),
    ctx.makeCommandOptions());

  ctx.face.processEvents();
}

void
RibModule::add(ExecuteContext& ctx)
{
  auto prefix = ctx.args.get<Name>("prefix");
  auto nexthop = ctx.args.at("nexthop");
  auto origin = ctx.args.get<RouteOrigin>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);
  auto cost = ctx.args.get<uint64_t>("cost", 0);
  bool wantChildInherit = !ctx.args.get<bool>("no-inherit", false);
  bool wantCapture = ctx.args.get<bool>("capture", false);
  auto expiresMillis = ctx.args.getOptional<uint64_t>("expires");

  auto registerRoute = [&] (uint64_t faceId) {
    ControlParameters registerParams;
    registerParams
      .setName(prefix)
      .setFaceId(faceId)
      .setOrigin(origin)
      .setCost(cost)
      .setFlags((wantChildInherit ? ndn::nfd::ROUTE_FLAG_CHILD_INHERIT : ndn::nfd::ROUTE_FLAGS_NONE) |
                (wantCapture ? ndn::nfd::ROUTE_FLAG_CAPTURE : ndn::nfd::ROUTE_FLAGS_NONE));
    if (expiresMillis) {
      registerParams.setExpirationPeriod(time::milliseconds(*expiresMillis));
    }

    ctx.controller.start<ndn::nfd::RibRegisterCommand>(
      registerParams,
      [&] (const ControlParameters& resp) {
        ctx.exitCode = static_cast<int>(FindFace::Code::OK);
        ctx.out << "route-add-accepted ";
        text::ItemAttributes ia;
        ctx.out << ia("prefix") << resp.getName()
                << ia("nexthop") << resp.getFaceId()
                << ia("origin") << resp.getOrigin()
                << ia("cost") << resp.getCost()
                << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
        if (resp.hasExpirationPeriod()) {
          ctx.out << ia("expires") << text::formatDuration<time::milliseconds>(resp.getExpirationPeriod()) << "\n";
        }
        else {
          ctx.out<< ia("expires") << "never\n";
        }
      },
      ctx.makeCommandFailureHandler("adding route"),
      ctx.makeCommandOptions());
  };

  auto handleFaceNotFound = [&] {
    const FaceUri* faceUri = std::any_cast<FaceUri>(&nexthop);
    if (faceUri == nullptr) {
      ctx.err << "Face not found\n";
      return;
    }

    if (faceUri->getScheme() == "ether") {
      // Unicast Ethernet faces require a LocalUri, which hasn't been provided
      // Multicast Ethernet faces cannot be created via management (already exist on each interface)
      ctx.err << "Unable to implicitly create Ethernet faces\n";
      ctx.err << "Please create the face with 'nfdc face create' before adding the route\n";
      return;
    }

    auto [canonized, error] = canonize(ctx, *faceUri);
    if (!canonized) {
      // Canonization failed
      auto canonizationError = canonizeErrorHelper(*faceUri, error);
      ctx.exitCode = static_cast<int>(canonizationError.first);
      ctx.err << canonizationError.second << '\n';
      return;
    }

    ControlParameters faceCreateParams;
    faceCreateParams.setUri(canonized->toString());

    ctx.controller.start<ndn::nfd::FaceCreateCommand>(
      faceCreateParams,
      [&] (const ControlParameters& resp) {
        FaceModule::printSuccess(ctx.out, "face-created", resp);
        registerRoute(resp.getFaceId());
      },
      ctx.makeCommandFailureHandler("implicitly creating face"),
      ctx.makeCommandOptions());
  };

  FindFace findFace(ctx);
  FindFace::Code res = findFace.execute(nexthop);

  ctx.exitCode = static_cast<int>(res);
  switch (res) {
    case FindFace::Code::OK:
      registerRoute(findFace.getFaceId());
      break;
    case FindFace::Code::ERROR:
    case FindFace::Code::CANONIZE_ERROR:
      ctx.err << findFace.getErrorReason() << '\n';
      return;
    case FindFace::Code::NOT_FOUND:
      // Attempt to create face if it doesn't exist
      handleFaceNotFound();
      break;
    case FindFace::Code::AMBIGUOUS:
      ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
      findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
      ctx.err << '\n';
      return;
    default:
      BOOST_ASSERT_MSG(false, "unexpected FindFace result");
      return;
  }

  ctx.face.processEvents();
}

void
RibModule::remove(ExecuteContext& ctx)
{
  auto prefix = ctx.args.get<Name>("prefix");
  auto nexthop = ctx.args.at("nexthop");
  auto origin = ctx.args.get<RouteOrigin>("origin", ndn::nfd::ROUTE_ORIGIN_STATIC);

  FindFace findFace(ctx);
  FindFace::Code res = findFace.execute(nexthop, true);

  ctx.exitCode = static_cast<int>(res);
  switch (res) {
    case FindFace::Code::OK:
      break;
    case FindFace::Code::ERROR:
    case FindFace::Code::CANONIZE_ERROR:
    case FindFace::Code::NOT_FOUND:
      ctx.err << findFace.getErrorReason() << '\n';
      return;
    default:
      BOOST_ASSERT_MSG(false, "unexpected FindFace result");
      return;
  }

  for (uint64_t faceId : findFace.getFaceIds()) {
    ControlParameters unregisterParams;
    unregisterParams
      .setName(prefix)
      .setFaceId(faceId)
      .setOrigin(origin);

    ctx.controller.start<ndn::nfd::RibUnregisterCommand>(
      unregisterParams,
      [&] (const ControlParameters& resp) {
        ctx.out << "route-removed ";
        text::ItemAttributes ia;
        ctx.out << ia("prefix") << resp.getName()
                << ia("nexthop") << resp.getFaceId()
                << ia("origin") << resp.getOrigin()
                << '\n';
      },
      ctx.makeCommandFailureHandler("removing route"),
      ctx.makeCommandOptions());
  }

  ctx.face.processEvents();
}

void
RibModule::fetchStatus(Controller& controller,
                       const std::function<void()>& onSuccess,
                       const Controller::DatasetFailCallback& onFailure,
                       const CommandOptions& options)
{
  controller.fetch<ndn::nfd::RibDataset>(
    [this, onSuccess] (const auto& result) {
      m_status = result;
      onSuccess();
    },
    onFailure, options);
}

void
RibModule::formatStatusXml(std::ostream& os) const
{
  os << "<rib>";
  for (const RibEntry& item : m_status) {
    this->formatItemXml(os, item);
  }
  os << "</rib>";
}

void
RibModule::formatItemXml(std::ostream& os, const RibEntry& item) const
{
  os << "<ribEntry>";

  os << "<prefix>" << xml::Text{item.getName().toUri()} << "</prefix>";

  os << "<routes>";
  for (const Route& route : item.getRoutes()) {
    os << "<route>"
       << "<faceId>" << route.getFaceId() << "</faceId>"
       << "<origin>" << route.getOrigin() << "</origin>"
       << "<cost>" << route.getCost() << "</cost>";
    if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
       os << "<flags/>";
    }
    else {
       os << "<flags>";
      if (route.isChildInherit()) {
        os << "<childInherit/>";
      }
      if (route.isRibCapture()) {
        os << "<ribCapture/>";
      }
      os << "</flags>";
    }
    if (route.hasExpirationPeriod()) {
      os << "<expirationPeriod>"
         << xml::formatDuration(time::duration_cast<time::seconds>(route.getExpirationPeriod()))
         << "</expirationPeriod>";
    }
    os << "</route>";
  }
  os << "</routes>";

  os << "</ribEntry>";
}

void
RibModule::formatStatusText(std::ostream& os) const
{
  os << "RIB:\n";
  for (const RibEntry& item : m_status) {
    os << "  ";
    formatEntryText(os, item);
    os << '\n';
  }
}

void
RibModule::formatEntryText(std::ostream& os, const RibEntry& entry)
{
  os << entry.getName() << " routes={";

  text::Separator sep(", ");
  for (const Route& route : entry.getRoutes()) {
    os << sep;
    formatRouteText(os, entry, route, false);
  }

  os << "}";
}

void
RibModule::formatRouteText(std::ostream& os, const RibEntry& entry, const Route& route,
                           bool includePrefix)
{
  text::ItemAttributes ia;

  if (includePrefix) {
    os << ia("prefix") << entry.getName();
  }
  os << ia("nexthop") << route.getFaceId();
  os << ia("origin") << route.getOrigin();
  os << ia("cost") << route.getCost();
  os << ia("flags") << static_cast<ndn::nfd::RouteFlags>(route.getFlags());
  if (route.hasExpirationPeriod()) {
    os << ia("expires") << text::formatDuration<time::seconds>(route.getExpirationPeriod());
  }
  else {
    os << ia("expires") << "never";
  }
}

} // namespace nfd::tools::nfdc
