#include<iostream>
#include<algorithm>

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

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;
	}
}
