#include <list>
#include <utility>
#include <algorithm>
#include "utility/nlsr_logger.hpp"
#include "nlsr_npt.hpp"
#include "nlsr_npte.hpp"
#include "nlsr.hpp"

#define THIS_FILE "nlsr_npt.cpp"

namespace nlsr
{

  using namespace std;

  static bool
  npteCompare(Npte& npte, string& name)
  {
    return npte.getNamePrefix()==name;
  }



  void
  Npt::addNpte(string name, RoutingTableEntry& rte, Nlsr& pnlsr)
  {
    std::list<Npte >::iterator it = std::find_if( m_npteList.begin(),
                                    m_npteList.end(), bind(&npteCompare, _1, name));
    if ( it == m_npteList.end() )
    {
      Npte newEntry(name);
      newEntry.addRoutingTableEntry(rte);
      newEntry.generateNhlfromRteList();
      newEntry.getNhl().sort();
      m_npteList.push_back(newEntry);
      if(rte.getNhl().getSize()> 0)
      {
        pnlsr.getFib().update(pnlsr, name,newEntry.getNhl());
      }
    }
    else
    {
      if ( rte.getNhl().getSize()> 0 )
      {
        (*it).addRoutingTableEntry(rte);
        (*it).generateNhlfromRteList();
        (*it).getNhl().sort();
        pnlsr.getFib().update(pnlsr, name,(*it).getNhl());
      }
      else
      {
        (*it).resetRteListNextHop();
        (*it).getNhl().reset();
        pnlsr.getFib().remove(pnlsr,name);
      }
    }
  }

  void
  Npt::removeNpte(string name, RoutingTableEntry& rte, Nlsr& pnlsr)
  {
    std::list<Npte >::iterator it = std::find_if( m_npteList.begin(),
                                    m_npteList.end(), bind(&npteCompare, _1, name));
    if ( it != m_npteList.end() )
    {
      string destRouter=rte.getDestination();
      (*it).removeRoutingTableEntry(rte);
      if ( ((*it).getRteListSize() == 0 ) &&
           (!pnlsr.getLsdb().doesLsaExist(destRouter+"/1",1) ) &&
           (!pnlsr.getLsdb().doesLsaExist(destRouter+"/2",2) ) &&
           (!pnlsr.getLsdb().doesLsaExist(destRouter+"/3",3) )   )
      {
        m_npteList.erase(it);
        pnlsr.getFib().remove(pnlsr,name);
      }
      else
      {
        (*it).generateNhlfromRteList();
        pnlsr.getFib().update(pnlsr, name,(*it).getNhl());
      }
    }
  }


  void
  Npt::addNpteByDestName(string name, string destRouter, Nlsr& pnlsr)
  {
    std::pair<RoutingTableEntry& , bool> rteCheck=
      pnlsr.getRoutingTable().findRoutingTableEntry(destRouter);
    if(rteCheck.second)
    {
      addNpte(name,rteCheck.first,pnlsr);
    }
    else
    {
      RoutingTableEntry rte(destRouter);
      addNpte(name, rte,pnlsr);
    }
  }

  void
  Npt::removeNpte(string name, string destRouter, Nlsr& pnlsr)
  {
    std::pair<RoutingTableEntry& , bool> rteCheck=
      pnlsr.getRoutingTable().findRoutingTableEntry(destRouter);
    if(rteCheck.second)
    {
      removeNpte(name,rteCheck.first,pnlsr);
    }
    else
    {
      RoutingTableEntry rte(destRouter);
      removeNpte(name, rte,pnlsr);
    }
  }

  void
  Npt::updateWithNewRoute(Nlsr& pnlsr)
  {
    for(std::list<Npte >::iterator it=m_npteList.begin(); it!=m_npteList.end(); ++it)
    {
      std::list<RoutingTableEntry> rteList=(*it).getRteList();
      for(std::list<RoutingTableEntry >::iterator rteit=rteList.begin();
          rteit !=rteList.end(); ++rteit)
      {
        std::pair<RoutingTableEntry& , bool> rteCheck=
          pnlsr.getRoutingTable().findRoutingTableEntry((*rteit).getDestination());
        if(rteCheck.second)
        {
          addNpte((*it).getNamePrefix(),rteCheck.first,pnlsr);
        }
        else
        {
          RoutingTableEntry rte((*rteit).getDestination());
          addNpte((*it).getNamePrefix(), rte,pnlsr);
        }
      }
    }
  }

  void
  Npt::print()
  {
    cout<<"----------------NPT----------------------"<<endl;
    for(std::list<Npte >::iterator it=m_npteList.begin(); it!=m_npteList.end(); ++it)
    {
      cout <<(*it)<<endl;
    }
  }

}
