/* -*- 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 "face-helpers.hpp"
#include "format-helpers.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 " + 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.getIoService(), 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
