/* -*- 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 "cs-module.hpp"
#include "format-helpers.hpp"

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

namespace nfd::tools::nfdc {

void
CsModule::registerCommands(CommandParser& parser)
{
  CommandDefinition defCsConfig("cs", "config");
  defCsConfig
    .setTitle("change CS configuration")
    .addArg("capacity", ArgValueType::UNSIGNED, Required::NO, Positional::NO)
    .addArg("admit", ArgValueType::BOOLEAN, Required::NO, Positional::NO)
    .addArg("serve", ArgValueType::BOOLEAN, Required::NO, Positional::NO);
  parser.addCommand(defCsConfig, &CsModule::config);

  CommandDefinition defCsErase("cs", "erase");
  defCsErase
    .setTitle("erase cached Data")
    .addArg("prefix", ArgValueType::NAME, Required::YES, Positional::YES)
    .addArg("count", ArgValueType::UNSIGNED, Required::NO, Positional::NO);
  parser.addCommand(defCsErase, &CsModule::erase);
}

void
CsModule::config(ExecuteContext& ctx)
{
  using boost::logic::indeterminate;

  auto capacity = ctx.args.getOptional<uint64_t>("capacity");
  auto enableAdmit = ctx.args.getTribool("admit");
  auto enableServe = ctx.args.getTribool("serve");

  ControlParameters p;
  if (capacity) {
    p.setCapacity(*capacity);
  }
  if (!indeterminate(enableAdmit)) {
    p.setFlagBit(ndn::nfd::BIT_CS_ENABLE_ADMIT, bool(enableAdmit));
  }
  if (!indeterminate(enableServe)) {
    p.setFlagBit(ndn::nfd::BIT_CS_ENABLE_SERVE, bool(enableServe));
  }

  ctx.controller.start<ndn::nfd::CsConfigCommand>(p,
    [&] (const ControlParameters& resp) {
      text::ItemAttributes ia;
      ctx.out << "cs-config-updated "
              << ia("capacity") << resp.getCapacity()
              << ia("admit") << text::OnOff{resp.getFlagBit(ndn::nfd::BIT_CS_ENABLE_ADMIT)}
              << ia("serve") << text::OnOff{resp.getFlagBit(ndn::nfd::BIT_CS_ENABLE_SERVE)}
              << '\n';
    },
    ctx.makeCommandFailureHandler("updating CS config"),
    ctx.makeCommandOptions());

  ctx.face.processEvents();
}

void
CsModule::erase(ExecuteContext& ctx)
{
  auto prefix = ctx.args.get<Name>("prefix");
  auto count = ctx.args.getOptional<uint64_t>("count");

  uint64_t numErased = 0;
  bool wasLimited = false;
  bool wasSuccessful = true;

  ControlParameters params;
  params.setName(prefix);

  // The cs/erase command can have a limit on the number of CS entries erased in a single operation.
  // Therefore, we may need to run cs/erase multiple times to achieve the desired number of erases.
  do {
    if (count) {
      params.setCount(*count - numErased);
    }

    wasSuccessful = false;

    ctx.controller.start<ndn::nfd::CsEraseCommand>(
      params,
      [&] (const ControlParameters& resp) {
        wasSuccessful = true;
        numErased += resp.getCount();
        wasLimited = resp.hasCapacity();
      },
      ctx.makeCommandFailureHandler("erasing cached Data"),
      ctx.makeCommandOptions());

    ctx.face.processEvents();
  } while (wasSuccessful && wasLimited);

  if (wasSuccessful) {
    text::ItemAttributes ia;
    ctx.out << "cs-erased "
            << ia("prefix") << prefix
            << ia("count") << numErased
            << '\n';
  }
}

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

void
CsModule::formatStatusXml(std::ostream& os) const
{
  formatItemXml(os, m_status);
}

void
CsModule::formatItemXml(std::ostream& os, const CsInfo& item)
{
  os << "<cs>";
  os << "<capacity>" << item.getCapacity() << "</capacity>";
  os << xml::Flag{"admitEnabled", item.getEnableAdmit()};
  os << xml::Flag{"serveEnabled", item.getEnableServe()};
  os << "<nEntries>" << item.getNEntries() << "</nEntries>";
  os << "<nHits>" << item.getNHits() << "</nHits>";
  os << "<nMisses>" << item.getNMisses() << "</nMisses>";
  os << "</cs>";
}

void
CsModule::formatStatusText(std::ostream& os) const
{
  os << "CS information:\n";
  ndn::util::IndentedStream indented(os, "  ");
  formatItemText(indented, m_status);
}

void
CsModule::formatItemText(std::ostream& os, const CsInfo& item)
{
  text::ItemAttributes ia(true, 8);
  os << ia("capacity") << item.getCapacity()
     << ia("admit") << text::OnOff{item.getEnableAdmit()}
     << ia("serve") << text::OnOff{item.getEnableServe()}
     << ia("nEntries") << item.getNEntries()
     << ia("nHits") << item.getNHits()
     << ia("nMisses") << item.getNMisses()
     << ia.end();
}

} // namespace nfd::tools::nfdc
