/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2017,  The 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/>.
 **/

#include "map.hpp"
#include "nlsr.hpp"
#include "adjacent.hpp"
#include "lsa.hpp"
#include "lsdb.hpp"
#include "logger.hpp"

#include <iostream>
#include <list>

namespace nlsr {

INIT_LOGGER("Map");

static bool
mapEntryCompareByRouter(MapEntry& mpe1, const ndn::Name& rtrName)
{
  return mpe1.getRouter() == rtrName;
}

static bool
mapEntryCompareByMappingNo(MapEntry& mpe1, int32_t mappingNo)
{
  return mpe1.getMappingNumber() == mappingNo;
}

void
Map::addEntry(const ndn::Name& rtrName)
{
  MapEntry me(rtrName, m_mappingIndex);
  if (addEntry(me)) {
    m_mappingIndex++;
  }
}

bool
Map::addEntry(MapEntry& mpe)
{
  //cout << mpe;
  std::list<MapEntry>::iterator it = std::find_if(m_table.begin(),
                                                  m_table.end(),
                                                  std::bind(&mapEntryCompareByRouter,
                                                            _1, mpe.getRouter()));
  if (it == m_table.end()) {
    m_table.push_back(mpe);
    return true;
  }
  return false;
}

const ndn::Name
Map::getRouterNameByMappingNo(int32_t mn)
{
  std::list<MapEntry>::iterator it = std::find_if(m_table.begin(),
                                                  m_table.end(),
                                                  std::bind(&mapEntryCompareByMappingNo,
                                                            _1, mn));
  if (it != m_table.end()) {
    return (*it).getRouter();
  }
  return ndn::Name();
}

int32_t
Map::getMappingNoByRouterName(const ndn::Name& rName)
{
  std::list<MapEntry>::iterator it = std::find_if(m_table.begin(),
                                                  m_table.end(),
                                                  std::bind(&mapEntryCompareByRouter,
                                                            _1, rName));
  if (it != m_table.end()) {
    return (*it).getMappingNumber();
  }
  return -1;
}

void
Map::reset()
{
  m_table.clear();
  m_mappingIndex = 0;
}

void
Map::writeLog()
{
  _LOG_DEBUG("---------------Map----------------------");
  for (std::list<MapEntry>::iterator it = m_table.begin(); it != m_table.end() ; it++) {
    _LOG_DEBUG("MapEntry: ( Router: " << (*it).getRouter() << " Mapping No: "
               << (*it).getMappingNumber() << " )");
  }
}

} // namespace nlsr
