/* -*- 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>
 *
 **/
#include "sync-logic-handler.hpp"

#include "conf-parameter.hpp"
#include "logger.hpp"
#include "lsa.hpp"
#include "lsdb.hpp"
#include "sequencing-manager.hpp"
#include "utility/name-helper.hpp"

#include <boost/serialization/shared_ptr.hpp>

using namespace boost::serialization;

namespace nlsr {

INIT_LOGGER("SyncLogicHandler");

using namespace ndn;
using namespace std;

class SyncUpdate
{
public:
  class Error : public std::runtime_error
  {
  public:
    explicit
    Error(const std::string& what)
      : std::runtime_error(what)
    {
    }
  };

public:
  SyncUpdate(const ndn::Name& name, uint64_t seqNo)
    : m_name(name)
    , m_seqManager(seqNo)
  {
  }

  const ndn::Name&
  getName() const
  {
    return m_name;
  }

  const ndn::Name
  getOriginRouter() const
  {
    int32_t nlsrPosition = util::getNameComponentPosition(m_name, NLSR_COMPONENT);
    int32_t lsaPosition = util::getNameComponentPosition(m_name, LSA_COMPONENT);

    if (nlsrPosition < 0 || lsaPosition < 0) {
      throw Error("Cannot parse update name because expected components are missing");
    }

    ndn::Name networkName = m_name.getSubName(0, nlsrPosition);
    ndn::Name routerName = m_name.getSubName(lsaPosition + 1);

    ndn::Name originRouter = networkName;
    originRouter.append(routerName);

    return originRouter;
  }

  uint64_t
  getNameLsaSeqNo() const
  {
    return m_seqManager.getNameLsaSeq();
  }

  uint64_t
  getAdjLsaSeqNo() const
  {
    return m_seqManager.getAdjLsaSeq();
  }

  uint64_t
  getCorLsaSeqNo() const
  {
    return m_seqManager.getCorLsaSeq();
  }

  const SequencingManager&
  getSequencingManager() const
  {
    return m_seqManager;
  }

private:
  const ndn::Name m_name;
  SequencingManager m_seqManager;

  static const std::string NLSR_COMPONENT;
  static const std::string LSA_COMPONENT;
};

const std::string SyncUpdate::NLSR_COMPONENT = "NLSR";
const std::string SyncUpdate::LSA_COMPONENT = "LSA";

const std::string SyncLogicHandler::NAME_COMPONENT = "name";
const std::string SyncLogicHandler::ADJACENCY_COMPONENT = "adjacency";
const std::string SyncLogicHandler::COORDINATE_COMPONENT = "coordinate";

void
SyncLogicHandler::createSyncSocket()
{
  _LOG_DEBUG("Creating Sync socket. Sync Prefix: " << m_syncPrefix);

  // The face's lifetime is managed in main.cpp; SyncSocket should not manage the memory
  // of the object
  ndn::shared_ptr<ndn::Face> facePtr(&m_syncFace, null_deleter());

  m_syncSocket = ndn::make_shared<Sync::SyncSocket>(m_syncPrefix, m_validator, facePtr,
                                                    ndn::bind(&SyncLogicHandler::onNsyncUpdate,
                                                              this, _1, _2),
                                                    ndn::bind(&SyncLogicHandler::onNsyncRemoval,
                                                              this, _1));
}

void
SyncLogicHandler::onNsyncUpdate(const vector<Sync::MissingDataInfo>& v, Sync::SyncSocket* socket)
{
  _LOG_DEBUG("Received Nsync update event");

  for (size_t i = 0; i < v.size(); i++){
    _LOG_DEBUG("Update Name: " << v[i].prefix << " Seq no: " << v[i].high.getSeq());

    SyncUpdate update(v[i].prefix, v[i].high.getSeq());

    processUpdateFromSync(update);
  }
}

void
SyncLogicHandler::onNsyncRemoval(const string& prefix)
{
  _LOG_DEBUG("Received Nsync removal event");
}

void
SyncLogicHandler::processUpdateFromSync(const SyncUpdate& update)
{
  ndn::Name originRouter;

  try {
    originRouter = update.getOriginRouter();
  }
  catch (std::exception& e) {
    _LOG_WARN("Received malformed sync update");
    return;
  }

  // A router should not try to fetch its own LSA
  if (originRouter != m_confParam.getRouterPrefix()) {

    update.getSequencingManager().writeLog();

    try {
      if (isLsaNew(originRouter, NAME_COMPONENT, update.getNameLsaSeqNo())) {
        _LOG_DEBUG("Received sync update with higher Name LSA sequence number than entry in LSDB");

        expressInterestForLsa(update, NAME_COMPONENT, update.getNameLsaSeqNo());
      }

      if (isLsaNew(originRouter, ADJACENCY_COMPONENT, update.getAdjLsaSeqNo())) {
        _LOG_DEBUG("Received sync update with higher Adj LSA sequence number than entry in LSDB");

        expressInterestForLsa(update, ADJACENCY_COMPONENT, update.getAdjLsaSeqNo());
      }

      if (isLsaNew(originRouter, COORDINATE_COMPONENT, update.getCorLsaSeqNo())) {
        _LOG_DEBUG("Received sync update with higher Cor LSA sequence number than entry in LSDB");

        expressInterestForLsa(update, COORDINATE_COMPONENT, update.getCorLsaSeqNo());
      }
    }
    catch (std::exception& e) {
      std::cerr << e.what() << std::endl;
      return;
    }
  }
}

bool
SyncLogicHandler::isLsaNew(const ndn::Name& originRouter, const std::string& lsaType,
                           uint64_t seqNo)
{
  ndn::Name lsaKey = originRouter;
  lsaKey.append(lsaType);

  if (lsaType == NAME_COMPONENT)
  {
    return m_lsdb.isNameLsaNew(lsaKey, seqNo);
  }
  else if (lsaType == ADJACENCY_COMPONENT)
  {
    return m_lsdb.isAdjLsaNew(lsaKey, seqNo);
  }
  else if (lsaType == COORDINATE_COMPONENT)
  {
    return m_lsdb.isCoordinateLsaNew(lsaKey, seqNo);
  }

  return false;
}

void
SyncLogicHandler::expressInterestForLsa(const SyncUpdate& update, std::string lsaType,
                                        uint64_t seqNo)
{
  ndn::Name interest(update.getName());
  interest.append(lsaType);
  interest.appendNumber(seqNo);

  m_lsdb.expressInterest(interest, 0);
}

void
SyncLogicHandler::publishRoutingUpdate(SequencingManager& manager, const ndn::Name& updatePrefix)
{
  manager.writeSeqNoToFile();
  publishSyncUpdate(updatePrefix, manager.getCombinedSeqNo());
}

void
SyncLogicHandler::publishSyncUpdate(const ndn::Name& updatePrefix, uint64_t seqNo)
{
  _LOG_DEBUG("Publishing Sync Update. Prefix: " << updatePrefix << " Seq No: " << seqNo);

  ndn::Name updateName(updatePrefix);
  string data("NoData");

  m_syncSocket->publishData(updateName.toUri(), 0, data.c_str(), data.size(), 1000, seqNo);
}

}//namespace nlsr
