/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2016,  Regents of the University of California,
 *                      Colorado State University,
 *                      University Pierre & Marie Curie, Sorbonne University.
 *
 * This file is part of ndn-tools (Named Data Networking Essential Tools).
 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
 *
 * ndn-tools 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.
 *
 * ndn-tools 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
 * ndn-tools, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Wentao Shang
 * @author Steve DiBenedetto
 * @author Andrea Tosatto
 */

#include "discover-version-iterative.hpp"

namespace ndn {
namespace chunks {

DiscoverVersionIterative::DiscoverVersionIterative(const Name& prefix, Face& face,
                                                   const Options& options)
  : chunks::Options(options)
  , DiscoverVersion(prefix, face, options)
  , Options(options)
  , m_latestVersion(0)
  , m_latestVersionData(nullptr)
  , m_foundVersion(false)
{
}

void
DiscoverVersionIterative::run()
{
  m_latestVersion = 0;
  m_foundVersion = false;

  Interest interest(m_prefix);
  interest.setInterestLifetime(interestLifetime);
  interest.setMustBeFresh(mustBeFresh);
  interest.setMinSuffixComponents(3);
  interest.setMaxSuffixComponents(3);
  interest.setChildSelector(1);

  expressInterest(interest, maxRetriesOnTimeoutOrNack, maxRetriesOnTimeoutOrNack);
}

void
DiscoverVersionIterative::handleData(const Interest& interest, const Data& data)
{
  size_t versionindex = m_prefix.size();

  const Name& name = data.getName();
  Exclude exclude;

  if (isVerbose)
    std::cerr << "Data: " << data << std::endl;

  BOOST_ASSERT(name.size() > m_prefix.size());
  if (name[versionindex].isVersion()) {
    m_latestVersion = name[versionindex].toVersion();
    m_latestVersionData = make_shared<Data>(data);
    m_foundVersion = true;

    exclude.excludeBefore(name[versionindex]);

    if (isVerbose)
      std::cerr << "Discovered version = " << m_latestVersion << std::endl;
  }
  else {
    // didn't find a version number at expected index.
    m_strayExcludes.excludeOne(name[versionindex]);
  }

  for (const auto& i : m_strayExcludes) {
    exclude.excludeOne(i.first);
  }

  Interest newInterest(interest);
  newInterest.refreshNonce();
  newInterest.setExclude(exclude);

  if (m_foundVersion)
    expressInterest(newInterest, maxRetriesOnTimeoutOrNack, maxRetriesAfterVersionFound);
  else
    expressInterest(interest, maxRetriesOnTimeoutOrNack, maxRetriesOnTimeoutOrNack);
}

void
DiscoverVersionIterative::handleTimeout(const Interest& interest, const std::string& reason)
{
  if (m_foundVersion) {
    // a version has been found and after a timeout error this version can be used as the latest.
    if (isVerbose)
      std::cerr << "Found data with the latest version: " << m_latestVersion << std::endl;

    // we discovered at least one version. assume what we have is the latest.
    this->emitSignal(onDiscoverySuccess, *m_latestVersionData);
  }
  else {
    DiscoverVersion::handleTimeout(interest, reason);
  }
}

} // namespace chunks
} // namespace ndn
