/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2025,  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 "procedure.hpp"
#include "guess-from-identity-name.hpp"
#include "guess-from-search-domains.hpp"
#include "multicast-discovery.hpp"
#include "ndn-fch-discovery.hpp"

#include <ndn-cxx/mgmt/nfd/control-command.hpp>

namespace ndn::autoconfig {

using nfd::ControlParameters;
using nfd::ControlResponse;

constexpr time::nanoseconds FACEURI_CANONIZE_TIMEOUT = 4_s;
const std::vector<Name> HUB_PREFIXES{"/", "/localhop/nfd"};
constexpr nfd::RouteOrigin HUB_ROUTE_ORIGIN = nfd::ROUTE_ORIGIN_AUTOCONF;
constexpr uint64_t HUB_ROUTE_COST = 100;

Procedure::Procedure(Face& face, KeyChain& keyChain)
  : m_face(face)
  , m_keyChain(keyChain)
  , m_controller(face, keyChain)
{
}

void
Procedure::initialize(const Options& options)
{
  BOOST_ASSERT(m_stages.empty());
  makeStages(options);
  BOOST_ASSERT(!m_stages.empty());

  for (size_t i = 0; i < m_stages.size(); ++i) {
    m_stages[i]->onSuccess.connect([this] (const auto& uri) { connect(uri); });
    if (i + 1 < m_stages.size()) {
      m_stages[i]->onFailure.connect([=] (const auto&) { m_stages[i + 1]->start(); });
    }
    else {
      m_stages[i]->onFailure.connect([=] (const auto&) { onComplete(false); });
    }
  }
}

void
Procedure::makeStages(const Options& options)
{
  m_stages.push_back(make_unique<MulticastDiscovery>(m_face, m_controller));
  m_stages.push_back(make_unique<GuessFromSearchDomains>());
  m_stages.push_back(make_unique<NdnFchDiscovery>(options.ndnFchUrl));
  m_stages.push_back(make_unique<GuessFromIdentityName>(m_keyChain));
}

void
Procedure::runOnce()
{
  BOOST_ASSERT(!m_stages.empty());
  m_stages.front()->start();
}

void
Procedure::connect(const FaceUri& hubFaceUri)
{
  hubFaceUri.canonize(
    [this] (const FaceUri& canonicalUri) {
      m_controller.start<nfd::FaceCreateCommand>(
        ControlParameters().setUri(canonicalUri.toString()),
        [this] (const ControlParameters& params) {
          std::cerr << "Connected to HUB " << params.getUri() << std::endl;
          this->registerPrefixes(params.getFaceId());
        },
        [this, canonicalUri] (const ControlResponse& resp) {
          if (resp.getCode() == 409) {
            ControlParameters params(resp.getBody());
            std::cerr << "Already connected to HUB " << params.getUri() << std::endl;
            this->registerPrefixes(params.getFaceId());
          }
          else {
            std::cerr << "Failed to connect to HUB " << canonicalUri << ": "
                      << resp.getText() << " (" << resp.getCode() << ")" << std::endl;
            this->onComplete(false);
          }
        });
    },
    [this] (const std::string& reason) {
      std::cerr << "Failed to canonize HUB FaceUri: " << reason << std::endl;
      this->onComplete(false);
    },
    m_face.getIoContext(), FACEURI_CANONIZE_TIMEOUT);
}

void
Procedure::registerPrefixes(uint64_t hubFaceId, size_t index)
{
  if (index >= HUB_PREFIXES.size()) {
    this->onComplete(true);
    return;
  }

  m_controller.start<nfd::RibRegisterCommand>(
    ControlParameters()
      .setName(HUB_PREFIXES[index])
      .setFaceId(hubFaceId)
      .setOrigin(HUB_ROUTE_ORIGIN)
      .setCost(HUB_ROUTE_COST),
    [=] (const ControlParameters&) {
      std::cerr << "Registered prefix " << HUB_PREFIXES[index] << std::endl;
      this->registerPrefixes(hubFaceId, index + 1);
    },
    [=] (const ControlResponse& resp) {
      std::cerr << "Failed to register " << HUB_PREFIXES[index] << ": "
                << resp.getText() << " (" << resp.getCode() << ")" << std::endl;
      this->onComplete(false);
    });
}

} // namespace ndn::autoconfig
