#include<iostream>
#include<algorithm>

#include "nlsr_adl.hpp"
#include "nlsr_adjacent.hpp"
#include "nlsr.hpp"

namespace nlsr
{

  Adl::Adl()
  {
  }

  Adl::~Adl()
  {
  }

  static bool
  adjacent_compare(Adjacent& adj1, Adjacent& adj2)
  {
    return adj1.getAdjacentName()==adj2.getAdjacentName();
  }

  int
  Adl::insert(Adjacent& adj)
  {
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if ( it != adjList.end() )
    {
      return -1;
    }
    adjList.push_back(adj);
    return 0;
  }

  void
  Adl::addAdjacentsFromAdl(Adl& adl)
  {
    for(std::list<Adjacent >::iterator it=adl.getAdjList().begin();
        it!=adl.getAdjList().end(); ++it)
    {
      insert((*it));
    }
  }

  int
  Adl::updateAdjacentStatus(string adjName, int s)
  {
    Adjacent adj(adjName);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it == adjList.end())
    {
      return -1;
    }
    (*it).setStatus(s);
    return 0;
  }

  Adjacent
  Adl::getAdjacent(string adjName)
  {
    Adjacent adj(adjName);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it != adjList.end())
    {
      return (*it);
    }
    return adj;
  }


  bool
  Adl::isAdlEqual(Adl &adl)
  {
    if ( getAdlSize() != adl.getAdlSize() )
    {
      return false;
    }
    adjList.sort(adjacent_compare);
    adl.getAdjList().sort(adjacent_compare);
    int equalAdjCount=0;
    std::list< Adjacent > adjList2=adl.getAdjList();
    std::list<Adjacent>::iterator it1;
    std::list<Adjacent>::iterator it2;
    for(it1=adjList.begin() , it2=adjList2.begin() ;
        it1!=adjList.end(); it1++,it2++)
    {
      if ( !(*it1).isAdjacentEqual((*it2)) )
      {
        break;
      }
      equalAdjCount++;
    }
    return equalAdjCount==getAdlSize();
  }


  int
  Adl::updateAdjacentLinkCost(string adjName, double lc)
  {
    Adjacent adj(adjName);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it == adjList.end())
    {
      return -1;
    }
    (*it).setLinkCost(lc);
    return 0;
  }

  bool
  Adl::isNeighbor(string adjName)
  {
    Adjacent adj(adjName);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it == adjList.end())
    {
      return false;
    }
    return true;
  }

  void
  Adl::incrementTimedOutInterestCount(string& neighbor)
  {
    Adjacent adj(neighbor);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it == adjList.end())
    {
      return ;
    }
    (*it).setInterestTimedOutNo((*it).getInterestTimedOutNo()+1);
  }

  void
  Adl::setTimedOutInterestCount(string& neighbor, int count)
  {
    Adjacent adj(neighbor);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it != adjList.end())
    {
      (*it).setInterestTimedOutNo(count);
    }
  }

  int
  Adl::getTimedOutInterestCount(string& neighbor)
  {
    Adjacent adj(neighbor);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it == adjList.end())
    {
      return -1;
    }
    return (*it).getInterestTimedOutNo();
  }

  int
  Adl::getStatusOfNeighbor(string& neighbor)
  {
    Adjacent adj(neighbor);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it == adjList.end())
    {
      return -1;
    }
    return (*it).getStatus();
  }

  void
  Adl::setStatusOfNeighbor(string& neighbor, int status)
  {
    Adjacent adj(neighbor);
    std::list<Adjacent >::iterator it = std::find_if( adjList.begin(),
                                        adjList.end(),
                                        bind(&adjacent_compare, _1, adj));
    if( it != adjList.end())
    {
      (*it).setStatus(status);
    }
  }

  std::list<Adjacent>&
  Adl::getAdjList()
  {
    return adjList;
  }

  bool
  Adl::isAdjLsaBuildable(Nlsr& pnlsr)
  {
    int nbrCount=0;
    for( std::list<Adjacent>::iterator it=adjList.begin();
         it!= adjList.end() ; it++)
    {
      if ( ((*it).getStatus() == 1 ) )
      {
        nbrCount++;
      }
      else
      {
        if ( (*it).getInterestTimedOutNo() >=
             pnlsr.getConfParameter().getInterestRetryNumber())
        {
          nbrCount++;
        }
      }
    }
    if( nbrCount == adjList.size())
    {
      return true;
    }
    return false;
  }

  int
  Adl::getNumOfActiveNeighbor()
  {
    int actNbrCount=0;
    for( std::list<Adjacent>::iterator it=adjList.begin();
         it!= adjList.end() ; it++)
    {
      if ( ((*it).getStatus() == 1 ) )
      {
        actNbrCount++;
      }
    }
    return actNbrCount;
  }

// used for debugging purpose
  void
  Adl::printAdl()
  {
    for( std::list<Adjacent>::iterator it=adjList.begin(); it!= adjList.end() ;
         it++)
    {
      cout<< (*it) <<endl;
    }
  }

} //namespace nlsr
