/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014  University of Memphis,
 *                     Regents of the University of California
 *
 * 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/>.
 *
 * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
 *
 **/

#ifndef NLSR_LSDB_HPP
#define NLSR_LSDB_HPP

#include <utility>
#include <boost/cstdint.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/util/time.hpp>

#include "lsa.hpp"
#include "test-access-control.hpp"

namespace nlsr {

using namespace ndn::time;

class Nlsr;

class Lsdb
{
public:
  Lsdb(Nlsr& nlsr, ndn::Scheduler& scheduler)
    : m_nlsr(nlsr)
    , m_scheduler(scheduler)
    , m_hasSyncPrefixBeenRegistered(false)
    , m_lsaRefreshTime(0)
  {
  }

  bool
  doesLsaExist(const ndn::Name& key, const std::string& lsType);
  // function related to Name LSDB

  bool
  buildAndInstallOwnNameLsa();

  NameLsa*
  findNameLsa(const ndn::Name& key);

  bool
  installNameLsa(NameLsa& nlsa);

  bool
  removeNameLsa(const ndn::Name& key);

  bool
  isNameLsaNew(const ndn::Name& key, uint64_t seqNo);

  void
  writeNameLsdbLog();

  //function related to Cor LSDB
  bool
  buildAndInstallOwnCoordinateLsa();

  CoordinateLsa*
  findCoordinateLsa(const ndn::Name& key);

  bool
  installCoordinateLsa(CoordinateLsa& clsa);

  bool
  removeCoordinateLsa(const ndn::Name& key);

  bool
  isCoordinateLsaNew(const ndn::Name& key, uint64_t seqNo);

  void
  writeCorLsdbLog();

  //function related to Adj LSDB
  void
  scheduledAdjLsaBuild();

  bool
  buildAndInstallOwnAdjLsa();

  bool
  removeAdjLsa(const ndn::Name& key);

  bool
  isAdjLsaNew(const ndn::Name& key, uint64_t seqNo);
  bool
  installAdjLsa(AdjLsa& alsa);

  AdjLsa*
  findAdjLsa(const ndn::Name& key);

  std::list<AdjLsa>&
  getAdjLsdb();

  void
  writeAdjLsdbLog();

  void
  setLsaRefreshTime(const seconds& lsaRefreshTime);

  void
  setThisRouterPrefix(std::string trp);

private:
  bool
  addNameLsa(NameLsa& nlsa);

  bool
  doesNameLsaExist(const ndn::Name& key);


  bool
  addCoordinateLsa(CoordinateLsa& clsa);

  bool
  doesCoordinateLsaExist(const ndn::Name& key);

  bool
  addAdjLsa(AdjLsa& alsa);

  bool
  doesAdjLsaExist(const ndn::Name& key);

  ndn::EventId
  scheduleNameLsaExpiration(const ndn::Name& key, int seqNo,
                            const seconds& expTime);

  void
  exprireOrRefreshNameLsa(const ndn::Name& lsaKey, uint64_t seqNo);

  ndn::EventId
  scheduleAdjLsaExpiration(const ndn::Name& key, int seqNo,
                           const seconds& expTime);

  void
  exprireOrRefreshAdjLsa(const ndn::Name& lsaKey, uint64_t seqNo);

  ndn::EventId
  scheduleCoordinateLsaExpiration(const ndn::Name& key, int seqNo,
                                  const seconds& expTime);

  void
  exprireOrRefreshCoordinateLsa(const ndn::Name& lsaKey,
                                uint64_t seqNo);
public:
  void
  expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
                  steady_clock::TimePoint deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);

  void
  processInterest(const ndn::Name& name, const ndn::Interest& interest);

private:
  void
  putLsaData(const ndn::Interest& interest, const std::string& content);

  void
  processInterestForNameLsa(const ndn::Interest& interest,
                            const ndn::Name& lsaKey,
                            uint64_t seqNo);

  void
  processInterestForAdjacencyLsa(const ndn::Interest& interest,
                                 const ndn::Name& lsaKey,
                                 uint64_t seqNo);

  void
  processInterestForCoordinateLsa(const ndn::Interest& interest,
                                  const ndn::Name& lsaKey,
                                  uint64_t seqNo);

  void
  onContent(const ndn::Data& data, const steady_clock::TimePoint& deadline,
            ndn::Name lsaName, uint64_t seqNo);

  /**
   * @brief Retry validation after it fails
   *
   * Data packet validation can fail either because the packet does not have
   * valid signature (fatal) or because some of the certificate chain Data packets
   * failed to be fetched (non-fatal).  Currently, the library does not provide
   * clear indication (besides plain-text message in error callback) of what is
   * the reason for failure and we will try to re-validate for as long as it the deadline.
   */
  void
  retryContentValidation(const ndn::shared_ptr<const ndn::Data>& data,
                         const steady_clock::TimePoint& deadline, ndn::Name lsaName,
                         uint64_t seqNo);

  void
  onContentValidated(const ndn::shared_ptr<const ndn::Data>& data);

  void
  onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const std::string& msg,
                            const steady_clock::TimePoint& deadline, ndn::Name lsaName,
                            uint64_t seqNo);

  void
  processContentNameLsa(const ndn::Name& lsaKey,
                        uint64_t lsSeqNo, std::string& dataContent);

  void
  processContentAdjacencyLsa(const ndn::Name& lsaKey,
                             uint64_t lsSeqNo, std::string& dataContent);

  void
  processContentCoordinateLsa(const ndn::Name& lsaKey,
                              uint64_t lsSeqNo, std::string& dataContent);

PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  void
  processInterestTimedOut(const ndn::Interest& interest, uint32_t retransmitNo,
                          const steady_clock::TimePoint& deadline, ndn::Name lsaName,
                          uint64_t seqNo);

private:
  system_clock::TimePoint
  getLsaExpirationTimePoint();

  void
  cancelScheduleLsaExpiringEvent(ndn::EventId eid);

private:
  Nlsr& m_nlsr;
  ndn::Scheduler& m_scheduler;

  std::list<NameLsa> m_nameLsdb;
  std::list<AdjLsa> m_adjLsdb;
  std::list<CoordinateLsa> m_corLsdb;

  bool m_hasSyncPrefixBeenRegistered;

  seconds m_lsaRefreshTime;
  std::string m_thisRouterPrefix;

  typedef std::map<ndn::Name, uint64_t> SequenceNumberMap;

  // Maps the name of an LSA to its highest known sequence number from sync;
  // Used to stop NLSR from trying to fetch outdated LSAs
  SequenceNumberMap m_highestSeqNo;

  static const ndn::time::seconds GRACE_PERIOD;
  static const steady_clock::TimePoint DEFAULT_LSA_RETRIEVAL_DEADLINE;
};

}//namespace nlsr

#endif //NLSR_LSDB_HPP
