/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2019,  The University of Memphis,
 *                           Regents of the University of California,
 *                           Arizona Board of Regents.
 *
 * This file is part of NLSR (Named-data Link State Routing).
 * See AUTHORS.md for complete list of NLSR authors and contributors.
 *
 * NLSR 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.
 *
 * NLSR 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
 * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "lsa-segment-storage.hpp"
#include "logger.hpp"
#include "lsa.hpp"
#include "utility/name-helper.hpp"
#include "conf-parameter.hpp"

namespace nlsr {

INIT_LOGGER(LsaSegmentStorage);

LsaSegmentStorage::LsaSegmentStorage(ndn::Scheduler& scheduler)
  : m_scheduler(scheduler)
{
}

void
LsaSegmentStorage::connectToFetcher(ndn::util::SegmentFetcher& fetcher)
{
  fetcher.afterSegmentValidated.connect(std::bind(&LsaSegmentStorage::afterFetcherSignalEmitted,
                                                  this, _1));
}

const ndn::Data*
LsaSegmentStorage::getLsaSegment(const ndn::Interest& interest)
{
  ndn::Name lsaSegmentsKey = interest.getName();

  // If this is the first interest then it does not contain the segment number,
  // so need to append zero segment component at the end to match with the data
  if (lsaSegmentsKey.size() > 0) {
    if (!lsaSegmentsKey.get(-1).isSegment()) {
      lsaSegmentsKey.appendSegment(0);
    }

    auto it = m_lsaSegments.find(lsaSegmentsKey);
    if (it == m_lsaSegments.end()) {
      NLSR_LOG_TRACE("Data for interest: " << interest.getName() << " cannot be found in the lsa storage");

      return nullptr;
    }
    else {
      NLSR_LOG_TRACE("Data for interest: " << interest.getName() << " is in the storage.");
      return &(it->second);
    }
  }
  else {
    NLSR_LOG_ERROR("Received interest has empty name.");
    return nullptr;
  }
}

void
LsaSegmentStorage::afterFetcherSignalEmitted(const ndn::Data& lsaSegment)
{
  NLSR_LOG_TRACE("Received a LSA segment: " << lsaSegment.getName());

  // lsaSegmentName is /<router-prefix>/<LS type>/<sequence no.>/<version no.>/<segment no.>
  auto lsaSegmentName = lsaSegment.getName();

  if (lsaSegmentName.size() > 0) {
    // lsaSegmentsKey is /<router-prefix>/<LS type>/<sequence no.>/<segment no.>
    ndn::Name lsaSegmentsKey(lsaSegmentName.getPrefix(lsaSegmentName.size() - 2));
    lsaSegmentsKey.append(lsaSegmentName.get(-1));

    // No need to store same LSA multiple time
    if (m_lsaSegments.find(lsaSegmentsKey) == m_lsaSegments.end()) {
      NLSR_LOG_TRACE("Received LSA segment is new. Storing it in the storage.");
      NLSR_LOG_TRACE("LSA data segment's name: " << lsaSegmentName);

      // Delete the same LSA with lower sequence number
      deleteOldLsas(lsaSegmentName);

      m_lsaSegments[lsaSegmentsKey] = lsaSegment;
    }
    else {
      NLSR_LOG_TRACE("The received segment is already in the storage.");
    }

    ndn::time::seconds expirationTime(LSA_REFRESH_TIME_DEFAULT);

    // schedule the segment deletion
    scheduleLsaSegmentDeletion(lsaSegmentsKey, expirationTime);
  }
  else {
    NLSR_LOG_ERROR("The received LSA segment has empty name.");
  }
}

void
LsaSegmentStorage::deleteOldLsas(const ndn::Name& newLsaName)
{
  auto newLsaKey = newLsaName.getPrefix(newLsaName.size() - 3);
  auto newSeqNo = newLsaName.get(-3).toNumber();

  std::vector<decltype(m_lsaSegments)::key_type> lsaToDelete;

  for (const auto& segment : m_lsaSegments) {
    ndn::Name segmentKey = segment.first;
    auto oldSeqNo = segmentKey.get(-2).toNumber();
    auto existingLsaKey = segmentKey.getPrefix(segmentKey.size() - 2);

    if (newLsaKey == existingLsaKey) {
      if (newSeqNo > oldSeqNo) { // in the key the second last component is the sequence number
        NLSR_LOG_TRACE("Outdated LSA: " << segmentKey << " with seq no: " <<
                       oldSeqNo << " is deleted.");
        lsaToDelete.push_back(segmentKey);
      }
    }
  }

  for (const auto& segmentKey : lsaToDelete) {
    m_lsaSegments.erase(segmentKey);
  }
}

void
LsaSegmentStorage::scheduleLsaSegmentDeletion(const ndn::Name& lsaSegmentsKey,
                                              ndn::time::seconds expirationTime)
{
  NLSR_LOG_TRACE("Scheduling LSA segment deletion for "
                 << lsaSegmentsKey << " in: " << expirationTime);
  m_scheduler.schedule(expirationTime,
                       [lsaSegmentsKey, this] { m_lsaSegments.erase(lsaSegmentsKey); });
}

} // namespace nlsr
