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

#include <ndn-cxx/mgmt/nfd/status-dataset.hpp>

namespace nfd::tools::nfdc {

void
StrategyChoiceModule::registerCommands(CommandParser& parser)
{
  CommandDefinition defStrategyList("strategy", "list");
  defStrategyList
    .setTitle("print strategy choices");
  parser.addCommand(defStrategyList, &StrategyChoiceModule::list);
  parser.addAlias("strategy", "list", "");

  CommandDefinition defStrategyShow("strategy", "show");
  defStrategyShow
    .setTitle("show strategy choice of an entry")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES);
  parser.addCommand(defStrategyShow, &StrategyChoiceModule::show);

  CommandDefinition defStrategySet("strategy", "set");
  defStrategySet
    .setTitle("set strategy choice for a name prefix")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
    .addArg("strategy", ArgValueType::NAME, Required::YES, Positional::YES);
  parser.addCommand(defStrategySet, &StrategyChoiceModule::set);

  CommandDefinition defStrategyUnset("strategy", "unset");
  defStrategyUnset
    .setTitle("clear strategy choice at a name prefix")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES);
  parser.addCommand(defStrategyUnset, &StrategyChoiceModule::unset);
}

void
StrategyChoiceModule::list(ExecuteContext& ctx)
{
  ctx.controller.fetch<ndn::nfd::StrategyChoiceDataset>(
    [&] (const std::vector<StrategyChoice>& dataset) {
      for (const StrategyChoice& entry : dataset) {
        formatItemText(ctx.out, entry);
        ctx.out << '\n';
      }
    },
    ctx.makeDatasetFailureHandler("strategy choice dataset"),
    ctx.makeCommandOptions());

  ctx.face.processEvents();
}

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

  ctx.controller.fetch<ndn::nfd::StrategyChoiceDataset>(
    [&] (const std::vector<StrategyChoice>& dataset) {
      StrategyChoice match; // longest prefix match
      for (const StrategyChoice& entry : dataset) {
        if (entry.getName().isPrefixOf(prefix) &&
            entry.getName().size() >= match.getName().size()) {
          match = entry;
        }
      }
      formatItemText(ctx.out, match, true);
    },
    ctx.makeDatasetFailureHandler("strategy choice dataset"),
    ctx.makeCommandOptions());

  ctx.face.processEvents();
}

void
StrategyChoiceModule::set(ExecuteContext& ctx)
{
  auto prefix = ctx.args.get<Name>("prefix");
  auto strategy = ctx.args.get<Name>("strategy");

  ctx.controller.start<ndn::nfd::StrategyChoiceSetCommand>(
    ControlParameters().setName(prefix).setStrategy(strategy),
    [&] (const ControlParameters& resp) {
      ctx.out << "strategy-set ";
      text::ItemAttributes ia;
      ctx.out << ia("prefix") << resp.getName()
              << ia("strategy") << resp.getStrategy() << '\n';
    },
    [&] (const ControlResponse& resp) {
      if (resp.getCode() == 404) {
        ctx.exitCode = 7;
        ctx.err << "Unknown strategy: " << strategy << '\n';
        ///\todo #3887 list available strategies
        return;
      }
      ctx.makeCommandFailureHandler("setting strategy")(resp); // invoke general error handler
    },
    ctx.makeCommandOptions());

  ctx.face.processEvents();
}

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

  if (prefix.empty()) {
    ctx.exitCode = 2;
    ctx.err << "Unsetting default strategy is prohibited\n";
    return;
  }

  ctx.controller.start<ndn::nfd::StrategyChoiceUnsetCommand>(
    ControlParameters().setName(prefix),
    [&] (const ControlParameters& resp) {
      ctx.out << "strategy-unset ";
      text::ItemAttributes ia;
      ctx.out << ia("prefix") << resp.getName() << '\n';
    },
    ctx.makeCommandFailureHandler("unsetting strategy"),
    ctx.makeCommandOptions());

  ctx.face.processEvents();
}

void
StrategyChoiceModule::fetchStatus(ndn::nfd::Controller& controller,
                                  const std::function<void()>& onSuccess,
                                  const ndn::nfd::DatasetFailureCallback& onFailure,
                                  const CommandOptions& options)
{
  controller.fetch<ndn::nfd::StrategyChoiceDataset>(
    [this, onSuccess] (const std::vector<StrategyChoice>& result) {
      m_status = result;
      onSuccess();
    },
    onFailure, options);
}

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

void
StrategyChoiceModule::formatItemXml(std::ostream& os, const StrategyChoice& item) const
{
  os << "<strategyChoice>";
  os << "<namespace>" << xml::Text{item.getName().toUri()} << "</namespace>";
  os << "<strategy><name>" << xml::Text{item.getStrategy().toUri()} << "</name></strategy>";
  os << "</strategyChoice>";
}

void
StrategyChoiceModule::formatStatusText(std::ostream& os) const
{
  os << "Strategy choices:\n";
  for (const StrategyChoice& item : m_status) {
    os << "  ";
    formatItemText(os, item);
    os << '\n';
  }
}

void
StrategyChoiceModule::formatItemText(std::ostream& os, const StrategyChoice& item, bool wantMultiLine)
{
  text::ItemAttributes ia(wantMultiLine, 8);
  os << ia("prefix") << item.getName()
     << ia("strategy") << item.getStrategy()
     << ia.end();
}

} // namespace nfd::tools::nfdc
