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

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

namespace nfd::tools::nfdc {

NDN_LOG_INIT(nfdc.FindFace);

FindFace::FindFace(ExecuteContext& ctx)
  : m_ctx(ctx)
{
}

FindFace::Code
FindFace::execute(const FaceUri& faceUri, bool allowMulti)
{
  FaceQueryFilter filter;
  filter.setRemoteUri(faceUri.toString());
  return this->execute(filter, allowMulti);
}

FindFace::Code
FindFace::execute(uint64_t faceId)
{
  FaceQueryFilter filter;
  filter.setFaceId(faceId);
  return this->execute(filter);
}

FindFace::Code
FindFace::execute(const std::any& faceIdOrUri, bool allowMulti)
{
  const uint64_t* faceId = std::any_cast<uint64_t>(&faceIdOrUri);
  if (faceId != nullptr) {
    return this->execute(*faceId);
  }
  else {
    return this->execute(std::any_cast<FaceUri>(faceIdOrUri), allowMulti);
  }
}

FindFace::Code
FindFace::execute(const FaceQueryFilter& filter, bool allowMulti)
{
  BOOST_ASSERT(m_res == Code::NOT_STARTED);
  m_res = Code::IN_PROGRESS;
  m_filter = filter;

  if (m_filter.hasRemoteUri()) {
    auto remoteUri = canonize("remote FaceUri", FaceUri(m_filter.getRemoteUri()));
    if (!remoteUri) {
      return m_res;
    }
    m_filter.setRemoteUri(remoteUri->toString());
  }

  if (m_filter.hasLocalUri()) {
    auto localUri = canonize("local FaceUri", FaceUri(m_filter.getLocalUri()));
    if (!localUri) {
      return m_res;
    }
    m_filter.setLocalUri(localUri->toString());
  }

  this->query();
  if (m_res == Code::OK) {
    if (m_results.size() == 0) {
      m_res = Code::NOT_FOUND;
      m_errorReason = "Face not found";
    }
    else if (m_results.size() > 1 && !allowMulti) {
      m_res = Code::AMBIGUOUS;
      m_errorReason = "Multiple faces match the query";
    }
  }
  return m_res;
}

std::optional<FaceUri>
FindFace::canonize(const std::string& fieldName, const FaceUri& uri)
{
  // We use a wrapper because we want to accept FaceUris that cannot be canonized
  if (!FaceUri::canCanonize(uri.getScheme())) {
    NDN_LOG_DEBUG("Using " << fieldName << "=" << uri << " without canonization");
    return uri;
  }

  auto [result, error] = nfdc::canonize(m_ctx, uri);
  if (result) {
    // Canonization succeeded
    return result;
  }
  else {
    // Canonization failed
    std::tie(m_res, m_errorReason) = canonizeErrorHelper(uri, error);
    return std::nullopt;
  }
}

void
FindFace::query()
{
  auto datasetCb = [this] (const auto& result) {
    m_res = Code::OK;
    m_results = result;
  };
  auto failureCb = [this] (uint32_t code, const auto& reason) {
    m_res = Code::ERROR;
    m_errorReason = "Error " + std::to_string(code) + " when querying face: " + reason;
  };

  if (m_filter.empty()) {
    m_ctx.controller.fetch<ndn::nfd::FaceDataset>(
      datasetCb, failureCb, m_ctx.makeCommandOptions());
  }
  else {
    m_ctx.controller.fetch<ndn::nfd::FaceQueryDataset>(
      m_filter, datasetCb, failureCb, m_ctx.makeCommandOptions());
  }
  m_ctx.face.processEvents();
}

std::set<uint64_t>
FindFace::getFaceIds() const
{
  std::set<uint64_t> faceIds;
  for (const FaceStatus& faceStatus : m_results) {
    faceIds.insert(faceStatus.getFaceId());
  }
  return faceIds;
}

const FaceStatus&
FindFace::getFaceStatus() const
{
  BOOST_ASSERT(m_results.size() == 1);
  return m_results.front();
}

void
FindFace::printDisambiguation(std::ostream& os, DisambiguationStyle style) const
{
  text::Separator sep(" ", ", ");
  for (const auto& item : m_results) {
    os << sep;
    switch (style) {
      case DisambiguationStyle::LOCAL_URI:
        os << item.getFaceId() << " (local=" << item.getLocalUri() << ')';
        break;
    }
  }
}

std::pair<std::optional<FaceUri>, std::string>
canonize(ExecuteContext& ctx, const FaceUri& uri)
{
  std::optional<FaceUri> result;
  std::string error;
  uri.canonize(
    [&result] (const auto& canonicalUri) { result = canonicalUri; },
    [&error] (const auto& errorReason) { error = errorReason; },
    ctx.face.getIoContext(), ctx.getTimeout());
  ctx.face.processEvents();

  return {result, error};
}

std::pair<FindFace::Code, std::string>
canonizeErrorHelper(const FaceUri& uri,
                    const std::string& error,
                    const std::string& field)
{
  std::string msg = "Error during canonization of ";
  if (!field.empty()) {
    msg += field + " ";
  }
  msg += "'" + uri.toString() + "': " + error;
  return {FindFace::Code::CANONIZE_ERROR, msg};
}

} // namespace nfd::tools::nfdc
