/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, 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.
 */

#include "validation-policy-command-interest.hpp"
#include "../pib/key.hpp"

namespace ndn {
namespace security {
namespace v2 {

ValidationPolicyCommandInterest::ValidationPolicyCommandInterest(unique_ptr<ValidationPolicy> inner,
                                                                 const Options& options)
  : m_options(options)
  , m_index(m_container.get<0>())
  , m_queue(m_container.get<1>())
{
  if (inner == nullptr) {
    BOOST_THROW_EXCEPTION(std::invalid_argument("inner policy is missing"));
  }
  setInnerPolicy(std::move(inner));

  m_options.gracePeriod = std::max(m_options.gracePeriod, time::nanoseconds::zero());
}

void
ValidationPolicyCommandInterest::checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
                                             const ValidationContinuation& continueValidation)
{
  getInnerPolicy().checkPolicy(data, state, continueValidation);
}

void
ValidationPolicyCommandInterest::checkPolicy(const Interest& interest, const shared_ptr<ValidationState>& state,
                                             const ValidationContinuation& continueValidation)
{
  bool isOk = false;
  Name keyName;
  uint64_t timestamp = 0;
  std::tie(isOk, keyName, timestamp) = parseCommandInterest(interest, state);
  if (!isOk) {
    return;
  }

  if (!checkTimestamp(state, keyName, timestamp)) {
    return;
  }
  getInnerPolicy().checkPolicy(interest, state, std::bind(continueValidation, _1, _2));
}

void
ValidationPolicyCommandInterest::cleanup()
{
  time::steady_clock::TimePoint expiring = time::steady_clock::now() - m_options.recordLifetime;

  while ((!m_queue.empty() && m_queue.front().lastRefreshed <= expiring) ||
         (m_options.maxRecords >= 0 &&
          m_queue.size() > static_cast<size_t>(m_options.maxRecords))) {
    m_queue.pop_front();
  }
}

std::tuple<bool, Name, uint64_t>
ValidationPolicyCommandInterest::parseCommandInterest(const Interest& interest,
                                                      const shared_ptr<ValidationState>& state) const
{
  const Name& name = interest.getName();
  if (name.size() < command_interest::MIN_SIZE) {
    state->fail({ValidationError::POLICY_ERROR, "Command interest name `" +
                 interest.getName().toUri() + "` is too short"});
    return std::make_tuple(false, Name(), 0);
  }

  const name::Component& timestampComp = name.at(command_interest::POS_TIMESTAMP);
  if (!timestampComp.isNumber()) {
    state->fail({ValidationError::POLICY_ERROR, "Command interest `" +
                 interest.getName().toUri() + "` doesn't include timestamp component"});
    return std::make_tuple(false, Name(), 0);
  }

  Name klName = getKeyLocatorName(interest, *state);
  if (!state->getOutcome()) { // already failed
    return std::make_tuple(false, Name(), 0);
  }

  return std::make_tuple(true, klName, timestampComp.toNumber());
}

bool
ValidationPolicyCommandInterest::checkTimestamp(const shared_ptr<ValidationState>& state,
                                                const Name& keyName, uint64_t timestamp)
{
  this->cleanup();

  time::system_clock::TimePoint now = time::system_clock::now();
  time::system_clock::TimePoint timestampPoint = time::fromUnixTimestamp(time::milliseconds(timestamp));
  if (timestampPoint < now - m_options.gracePeriod || timestampPoint > now + m_options.gracePeriod) {
    state->fail({ValidationError::POLICY_ERROR, "Timestamp is outside the grace period for key " + keyName.toUri()});
    return false;
  }
  auto it = m_index.find(keyName);
  if (it != m_index.end()) {
    if (timestamp <= it->timestamp) {
      state->fail({ValidationError::POLICY_ERROR, "Timestamp is reordered for key " + keyName.toUri()});
      return false;
    }
  }

  shared_ptr<InterestValidationState> interestState = std::dynamic_pointer_cast<InterestValidationState>(state);
  interestState->afterSuccess.connect(bind(&ValidationPolicyCommandInterest::insertNewRecord,
                                           this, _1, keyName, timestamp));
  return true;
}

void
ValidationPolicyCommandInterest::insertNewRecord(const Interest& interest, const Name& keyName,
                                                 uint64_t timestamp)
{
  // try to insert new record
  time::steady_clock::TimePoint now = time::steady_clock::now();
  Queue::iterator i = m_queue.end();
  bool isNew = false;
  LastTimestampRecord newRecord{keyName, timestamp, now};
  std::tie(i, isNew) = m_queue.push_back(newRecord);

  if (!isNew) {
    BOOST_ASSERT(i->keyName == keyName);

    // set lastRefreshed field, and move to queue tail
    m_queue.erase(i);
    isNew = m_queue.push_back(newRecord).second;
    BOOST_VERIFY(isNew);
  }
}

} // namespace v2
} // namespace security
} // namespace ndn
