#include<string>
#include<utility>
#include "nlsr_lsdb.hpp"
#include "nlsr.hpp"

using namespace std;

static bool
nameLsaCompareByKey(NameLsa& nlsa1, string& key){
	return nlsa1.getNameLsaKey()==key;
}


bool
Lsdb::buildAndInstallOwnNameLsa(nlsr& pnlsr)
{
	NameLsa nameLsa(pnlsr.getConfParameter().getRouterPrefix()
					, 1
					, pnlsr.getSm().getNameLsaSeq()+1
					, pnlsr.getConfParameter().getRouterDeadInterval()
					, pnlsr.getNpl() );
	pnlsr.getSm().setNameLsaSeq(pnlsr.getSm().getNameLsaSeq()+1);
	return installNameLsa(pnlsr,nameLsa);

}

std::pair<NameLsa&, bool> 
Lsdb::getNameLsa(string key)
{
	std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(), 
																		nameLsdb.end(),	
   																	bind(nameLsaCompareByKey, _1, key));

	if( it != nameLsdb.end())
	{
		return std::make_pair(boost::ref((*it)),true);
	}

	NameLsa nlsa;
	return std::make_pair(boost::ref(nlsa),false);

}


void 
Lsdb::scheduleNameLsaExpiration(nlsr& pnlsr, string key, int seqNo, int expTime)
{
	pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(expTime),
								                      ndn::bind(&Lsdb::exprireOrRefreshNameLsa,
								                      this,boost::ref(pnlsr), key, seqNo));
}

bool 
Lsdb::installNameLsa(nlsr& pnlsr, NameLsa &nlsa)
{
	int timeToExpire=lsaRefreshTime;
	std::pair<NameLsa& , bool> chkNameLsa=getNameLsa(nlsa.getNameLsaKey());
	if ( !chkNameLsa.second )
	{
		addNameLsa(nlsa);
		printNameLsdb();
		if ( nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
		{
			pnlsr.getNpt().addNpte(nlsa.getOrigRouter(),nlsa.getOrigRouter(),pnlsr);
			std::list<string> nameList=nlsa.getNpl().getNameList();
			for(std::list<string>::iterator it=nameList.begin(); it!=nameList.end();it++)
			{
				if ( (*it) !=pnlsr.getConfParameter().getRouterPrefix())
				{
					pnlsr.getNpt().addNpte((*it),nlsa.getOrigRouter(),pnlsr);
				}
			}
		}

		if(nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
		{
			timeToExpire=nlsa.getLifeTime();
		}
		scheduleNameLsaExpiration( pnlsr, nlsa.getNameLsaKey(),
			                                         nlsa.getLsSeqNo(), timeToExpire);
	}
	else
	{
		if ( chkNameLsa.first.getLsSeqNo() < nlsa.getLsSeqNo() )
		{
			chkNameLsa.first.setLsSeqNo(nlsa.getLsSeqNo());
			chkNameLsa.first.setLifeTime(nlsa.getLifeTime());

			chkNameLsa.first.getNpl().sortNpl();
			nlsa.getNpl().sortNpl();

			std::list<string> nameToAdd;
			std::set_difference(nlsa.getNpl().getNameList().begin(),
			                    nlsa.getNpl().getNameList().end(),
			                    chkNameLsa.first.getNpl().getNameList().begin(),
			                    chkNameLsa.first.getNpl().getNameList().end(),
                          std::inserter(nameToAdd, nameToAdd.begin()));
      for(std::list<string>::iterator it=nameToAdd.begin(); it!=nameToAdd.end();
                                                                           ++it)
      {
      		chkNameLsa.first.addNameToLsa((*it));
      		if ( nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
      		{
      			if ( (*it) !=pnlsr.getConfParameter().getRouterPrefix())
      			{
      				pnlsr.getNpt().addNpte((*it),nlsa.getOrigRouter(),pnlsr);
      			}
      		}
      }
                          
      std::list<string> nameToRemove;
      std::set_difference(chkNameLsa.first.getNpl().getNameList().begin(),
			                    chkNameLsa.first.getNpl().getNameList().end(),
			                    nlsa.getNpl().getNameList().begin(),
			                    nlsa.getNpl().getNameList().end(),
                          std::inserter(nameToRemove, nameToRemove.begin()));
      for(std::list<string>::iterator it=nameToRemove.begin(); 
                                                   it!=nameToRemove.end(); ++it)
      {
      		chkNameLsa.first.removeNameFromLsa((*it));
      		if ( nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
      		{
      			if ( (*it) !=pnlsr.getConfParameter().getRouterPrefix())
      			{
      				pnlsr.getNpt().removeNpte((*it),nlsa.getOrigRouter(),pnlsr);
      			}
      		}
      } 

			if(nlsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
			{
				timeToExpire=nlsa.getLifeTime();
			}
			scheduleNameLsaExpiration( pnlsr, nlsa.getNameLsaKey(),
			                                         nlsa.getLsSeqNo(), timeToExpire);
		}
	}
	
	return true;
}

bool 
Lsdb::addNameLsa(NameLsa &nlsa)
{
	std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(), 
					 nameLsdb.end(), bind(nameLsaCompareByKey, _1, nlsa.getNameLsaKey()));

	if( it == nameLsdb.end())
	{
		nameLsdb.push_back(nlsa);
		return true;
	}
	return false;
}

bool 
Lsdb::removeNameLsa(nlsr& pnlsr, string& key)
{
	std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(), 
																		nameLsdb.end(),	
   																	bind(nameLsaCompareByKey, _1, key));
  if ( it != nameLsdb.end() )
  {
  		if ( (*it).getOrigRouter() != pnlsr.getConfParameter().getRouterPrefix()  )
  		{
  			pnlsr.getNpt().removeNpte((*it).getOrigRouter(),(*it).getOrigRouter(),pnlsr);	
  			for( std::list<string>::iterator nit=(*it).getNpl().getNameList().begin();
  			                           nit!=(*it).getNpl().getNameList().end(); ++nit)
  			{
  				if ( (*nit) !=pnlsr.getConfParameter().getRouterPrefix())
  				{
  					pnlsr.getNpt().removeNpte((*nit),(*it).getOrigRouter(),pnlsr);
  				}
  			} 
  			
  		}
		nameLsdb.erase(it);
		return true;
  }
	return false;
}

bool 
Lsdb::doesNameLsaExist(string key)
{
	std::list<NameLsa >::iterator it = std::find_if( nameLsdb.begin(), 
																		nameLsdb.end(),	
   																	bind(nameLsaCompareByKey, _1, key));

	if( it == nameLsdb.end()){
		return false;
	}

	return true;
}

void 
Lsdb::printNameLsdb()
{
	cout<<"---------------Name LSDB-------------------"<<endl;
	for( std::list<NameLsa>::iterator it=nameLsdb.begin(); 
	                                                 it!= nameLsdb.end() ; it++)
	{
		cout<< (*it) <<endl;
	}
}

// Cor LSA and LSDB related Functions start here


static bool
corLsaCompareByKey(CorLsa& clsa, string& key){
	return clsa.getCorLsaKey()==key;
}

bool 
Lsdb::buildAndInstallOwnCorLsa(nlsr& pnlsr){
	CorLsa corLsa(pnlsr.getConfParameter().getRouterPrefix()
					, 3
					, pnlsr.getSm().getCorLsaSeq()+1
					, pnlsr.getConfParameter().getRouterDeadInterval()
					, pnlsr.getConfParameter().getCorR()
					, pnlsr.getConfParameter().getCorTheta() );
	pnlsr.getSm().setCorLsaSeq(pnlsr.getSm().getCorLsaSeq()+1);
	installCorLsa(pnlsr, corLsa);

	return true;
}

std::pair<CorLsa&, bool> 
Lsdb::getCorLsa(string key)
{
	std::list< CorLsa >::iterator it = std::find_if( corLsdb.begin(), 
																		corLsdb.end(),	
   																	bind(corLsaCompareByKey, _1, key));

	if( it != corLsdb.end()){
		return std::make_pair(boost::ref((*it)), true);
	}

	CorLsa clsa;
	return std::make_pair(boost::ref(clsa),false);
}

void
Lsdb::scheduleCorLsaExpiration(nlsr& pnlsr, string key, int seqNo, int expTime)
{
	pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(expTime),
								                      ndn::bind(&Lsdb::exprireOrRefreshCorLsa,
								                      this,boost::ref(pnlsr),key,seqNo));
}

bool 
Lsdb::installCorLsa(nlsr& pnlsr, CorLsa &clsa)
{
	int timeToExpire=lsaRefreshTime;
	std::pair<CorLsa& , bool> chkCorLsa=getCorLsa(clsa.getCorLsaKey());
	if ( !chkCorLsa.second )
	{
		addCorLsa(clsa);
		printCorLsdb(); //debugging purpose
		if ( clsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
		{
			pnlsr.getNpt().addNpte(clsa.getOrigRouter(),clsa.getOrigRouter(),pnlsr);
		}
		if (pnlsr.getConfParameter().getIsHyperbolicCalc() >=1 )
		{
			pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);	
		}

		if(clsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
		{
				timeToExpire=clsa.getLifeTime();
		}
	  scheduleCorLsaExpiration(pnlsr,clsa.getCorLsaKey(),
	                                         clsa.getLsSeqNo(), timeToExpire);
		
	}
	else
	{
		if ( chkCorLsa.first.getLsSeqNo() < clsa.getLsSeqNo() )
		{
			chkCorLsa.first.setLsSeqNo(clsa.getLsSeqNo());
			chkCorLsa.first.setLifeTime(clsa.getLifeTime());
			if ( !chkCorLsa.first.isLsaContentEqual(clsa) )
			{
				chkCorLsa.first.setCorRadius(clsa.getCorRadius());
				chkCorLsa.first.setCorTheta(clsa.getCorTheta());

				if (pnlsr.getConfParameter().getIsHyperbolicCalc() >=1 )
				{
					pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);	
				}
				
			}

			if(clsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
			{
				timeToExpire=clsa.getLifeTime();
			}
			scheduleCorLsaExpiration(pnlsr,clsa.getCorLsaKey(),
	                                         clsa.getLsSeqNo(), timeToExpire);
		}
		
	}
	
	return true;
}

bool 
Lsdb::addCorLsa(CorLsa& clsa)
{
	std::list<CorLsa >::iterator it = std::find_if( corLsdb.begin(), 
																		corLsdb.end(),	
   														bind(corLsaCompareByKey, _1, clsa.getCorLsaKey()));

	if( it == corLsdb.end())
	{
		corLsdb.push_back(clsa);
		return true;
	}
	return false;
}

bool 
Lsdb::removeCorLsa(nlsr& pnlsr, string& key)
{
	std::list<CorLsa >::iterator it = std::find_if( corLsdb.begin(), 
																		corLsdb.end(),	
   																	bind(corLsaCompareByKey, _1, key));
  if ( it != corLsdb.end() )
  {
  		if ( (*it).getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
		{
			pnlsr.getNpt().removeNpte((*it).getOrigRouter(),(*it).getOrigRouter(),pnlsr);
		}
		corLsdb.erase(it);
		return true;
  }
	return false;

}

bool 
Lsdb::doesCorLsaExist(string key)
{
	std::list<CorLsa >::iterator it = std::find_if( corLsdb.begin(), 
																		corLsdb.end(),	
   																	bind(corLsaCompareByKey, _1, key));

	if( it == corLsdb.end()){
		return false;
	}

	return true;
}

void 
Lsdb::printCorLsdb() //debugging
{
	cout<<"---------------Cor LSDB-------------------"<<endl;
	for( std::list<CorLsa>::iterator it=corLsdb.begin(); 
	                                                 it!= corLsdb.end() ; it++)
	{
		cout<< (*it) <<endl;
	}
}


// Adj LSA and LSDB related function starts here

static bool
adjLsaCompareByKey(AdjLsa& alsa, string& key){
	return alsa.getAdjLsaKey()==key;
}


void 
Lsdb::scheduledAdjLsaBuild(nlsr& pnlsr)
{
	cout<<"scheduledAdjLsaBuild Called"<<endl;
	pnlsr.setIsBuildAdjLsaSheduled(0);

	if( pnlsr.getAdl().isAdjLsaBuildable(pnlsr))
	{
		int adjBuildCount=pnlsr.getAdjBuildCount();
		if(adjBuildCount>0 )
		{
			if (pnlsr.getAdl().getNumOfActiveNeighbor()>0)
			{
				buildAndInstallOwnAdjLsa(pnlsr);
			}
			else
			{
				string key=pnlsr.getConfParameter().getRouterPrefix()+"/2";
				removeAdjLsa(pnlsr,key);
				pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
			}
			pnlsr.setAdjBuildCount(pnlsr.getAdjBuildCount()-adjBuildCount);
		}		
	}
	else
	{
		pnlsr.setIsBuildAdjLsaSheduled(1);
		int schedulingTime=pnlsr.getConfParameter().getInterestRetryNumber()*
		                   pnlsr.getConfParameter().getInterestResendTime();
		pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(schedulingTime),
							ndn::bind(&Lsdb::scheduledAdjLsaBuild, pnlsr.getLsdb(), 
																									boost::ref(pnlsr)));
	}

}


bool 
Lsdb::addAdjLsa(AdjLsa &alsa)
{
	std::list<AdjLsa >::iterator it = std::find_if( adjLsdb.begin(), 
																		adjLsdb.end(),	
   														bind(adjLsaCompareByKey, _1, alsa.getAdjLsaKey()));

	if( it == adjLsdb.end()){
		adjLsdb.push_back(alsa);
		return true;
	}
	return false;
	
}

std::pair<AdjLsa& , bool> 
Lsdb::getAdjLsa(string key)
{
	std::list<AdjLsa >::iterator it = std::find_if( adjLsdb.begin(), 
																		adjLsdb.end(),	
   																	bind(adjLsaCompareByKey, _1, key));

	if( it != adjLsdb.end()){
		return std::make_pair(boost::ref((*it)),true);
	}

	AdjLsa alsa;
	return std::make_pair(boost::ref(alsa),false);
}



void 
Lsdb::scheduleAdjLsaExpiration(nlsr& pnlsr, string key, int seqNo, int expTime)
{
	pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(expTime),
								                      ndn::bind(&Lsdb::exprireOrRefreshAdjLsa,
								                      this,boost::ref(pnlsr),key,seqNo));
}

bool 
Lsdb::installAdjLsa(nlsr& pnlsr, AdjLsa &alsa)
{
	int timeToExpire=lsaRefreshTime;
	std::pair<AdjLsa& , bool> chkAdjLsa=getAdjLsa(alsa.getAdjLsaKey());
	if ( !chkAdjLsa.second )
	{
		addAdjLsa(alsa);
		alsa.addNptEntriesForAdjLsa(pnlsr);
		pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);

		if(alsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
		{
				timeToExpire=alsa.getLifeTime();
		}
		scheduleAdjLsaExpiration(pnlsr,alsa.getAdjLsaKey(),
		                                            alsa.getLsSeqNo(),timeToExpire);
		
	}
	else
	{
		if ( chkAdjLsa.first.getLsSeqNo() < alsa.getLsSeqNo() )
		{
			chkAdjLsa.first.setLsSeqNo(alsa.getLsSeqNo());
			chkAdjLsa.first.setLifeTime(alsa.getLifeTime());

			if ( !	chkAdjLsa.first.isLsaContentEqual(alsa))
			{
				chkAdjLsa.first.getAdl().resetAdl();
				chkAdjLsa.first.getAdl().addAdjacentsFromAdl(alsa.getAdl());
				pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);	
			}
			
			if(alsa.getOrigRouter() !=pnlsr.getConfParameter().getRouterPrefix() )
			{
				timeToExpire=alsa.getLifeTime();
			}
			scheduleAdjLsaExpiration(pnlsr,alsa.getAdjLsaKey(),
		                                            alsa.getLsSeqNo(),timeToExpire);
		}
		
	}

	printAdjLsdb();
	
	return true;
}

bool 
Lsdb::buildAndInstallOwnAdjLsa(nlsr& pnlsr)
{
	AdjLsa adjLsa(pnlsr.getConfParameter().getRouterPrefix()
					, 2
					, pnlsr.getSm().getAdjLsaSeq()+1
					, pnlsr.getConfParameter().getRouterDeadInterval()
					, pnlsr.getAdl().getNumOfActiveNeighbor()
					, pnlsr.getAdl() );
	pnlsr.getSm().setAdjLsaSeq(pnlsr.getSm().getAdjLsaSeq()+1);
	return installAdjLsa(pnlsr, adjLsa);
}

bool 
Lsdb::removeAdjLsa(nlsr& pnlsr, string& key)
{
	std::list<AdjLsa >::iterator it = std::find_if( adjLsdb.begin(), 
																		adjLsdb.end(),	
   																	bind(adjLsaCompareByKey, _1, key));
  if ( it != adjLsdb.end() )
  {
  		(*it).removeNptEntriesForAdjLsa(pnlsr);
		adjLsdb.erase(it);
		return true;
  }
	return false;
	
}

bool 
Lsdb::doesAdjLsaExist(string key)
{
	std::list< AdjLsa >::iterator it = std::find_if( adjLsdb.begin(), 
																		adjLsdb.end(),	
   																	bind(adjLsaCompareByKey, _1, key));

	if( it == adjLsdb.end()){
		return false;
	}

	return true;
}

std::list<AdjLsa>& 
Lsdb::getAdjLsdb()
{
		return adjLsdb;
}

void 
Lsdb::setLsaRefreshTime(int lrt)
{
	lsaRefreshTime=lrt;
}

void 
Lsdb::setThisRouterPrefix(string trp)
{
	thisRouterPrefix=trp;
}

void 
Lsdb::exprireOrRefreshNameLsa(nlsr& pnlsr, string lsaKey, int seqNo)
{
	cout<<"Lsdb::exprireOrRefreshNameLsa Called "<<endl;
	cout<<"LSA Key : "<<lsaKey<<" Seq No: "<<endl;
	std::pair<NameLsa& , bool> chkNameLsa=getNameLsa(lsaKey);
	if( chkNameLsa.second )
	{
		cout<<" LSA Exists with seq no: "<<chkNameLsa.first.getLsSeqNo()<<endl;
		if ( chkNameLsa.first.getLsSeqNo() == seqNo )
		{
			if(chkNameLsa.first.getOrigRouter() == thisRouterPrefix )
			{
				cout<<"Own Name LSA, so refreshing name LSA"<<endl;
				chkNameLsa.first.setLsSeqNo(chkNameLsa.first.getLsSeqNo()+1);
				pnlsr.getSm().setNameLsaSeq(chkNameLsa.first.getLsSeqNo());
				// publish routing update
			}
			else
			{
				cout<<"Other's Name LSA, so removing form LSDB"<<endl;
				removeNameLsa(pnlsr, lsaKey);
			}
		}
	}
}

void 
Lsdb::exprireOrRefreshAdjLsa(nlsr& pnlsr, string lsaKey, int seqNo)
{
	cout<<"Lsdb::exprireOrRefreshAdjLsa Called "<<endl;
	cout<<"LSA Key : "<<lsaKey<<" Seq No: "<<endl;
	std::pair<AdjLsa& , bool> chkAdjLsa=getAdjLsa(lsaKey);
	if( chkAdjLsa.second )
	{
		cout<<" LSA Exists with seq no: "<<chkAdjLsa.first.getLsSeqNo()<<endl;
		if ( chkAdjLsa.first.getLsSeqNo() == seqNo )
		{
			if(chkAdjLsa.first.getOrigRouter() == thisRouterPrefix )
			{
				cout<<"Own Adj LSA, so refreshing Adj LSA"<<endl;
				chkAdjLsa.first.setLsSeqNo(chkAdjLsa.first.getLsSeqNo()+1);
				pnlsr.getSm().setAdjLsaSeq(chkAdjLsa.first.getLsSeqNo());
				// publish routing update
			}
			else
			{
				cout<<"Other's Adj LSA, so removing form LSDB"<<endl;
				removeAdjLsa(pnlsr, lsaKey);
			}

			// schedule Routing table calculaiton
			pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);
		}
	}
}

void 
Lsdb::exprireOrRefreshCorLsa(nlsr& pnlsr, string lsaKey, int seqNo)
{
	cout<<"Lsdb::exprireOrRefreshCorLsa Called "<<endl;
	cout<<"LSA Key : "<<lsaKey<<" Seq No: "<<endl;
	std::pair<CorLsa& , bool> chkCorLsa=getCorLsa(lsaKey);
	if( chkCorLsa.second )
	{
		cout<<" LSA Exists with seq no: "<<chkCorLsa.first.getLsSeqNo()<<endl;
		if ( chkCorLsa.first.getLsSeqNo() == seqNo )
		{
			if(chkCorLsa.first.getOrigRouter() == thisRouterPrefix )
			{
				cout<<"Own Cor LSA, so refreshing Cor LSA"<<endl;
				chkCorLsa.first.setLsSeqNo(chkCorLsa.first.getLsSeqNo()+1);
				pnlsr.getSm().setCorLsaSeq(chkCorLsa.first.getLsSeqNo());
				// publish routing update
			}
			else
			{
				cout<<"Other's Cor LSA, so removing form LSDB"<<endl;
				removeCorLsa(pnlsr, lsaKey);
			}

			if (pnlsr.getConfParameter().getIsHyperbolicCalc() >=1 )
			{
				pnlsr.getRoutingTable().scheduleRoutingTableCalculation(pnlsr);	
			}
		}
	}
}


void 
Lsdb::printAdjLsdb()
{
	cout<<"---------------Adj LSDB-------------------"<<endl;
	for( std::list<AdjLsa>::iterator it=adjLsdb.begin(); 
	                                                 it!= adjLsdb.end() ; it++)
	{
		cout<< (*it) <<endl;
	}
}

//-----utility function -----
bool 
Lsdb::doesLsaExist(string key, int lsType)
{
	if ( lsType == 1)
	{
		return doesNameLsaExist(key);
	}
	else if ( lsType == 2)
	{
		return doesAdjLsaExist(key);
	}
	else if ( lsType == 3)
	{
		return doesCorLsaExist(key);
	}
	
	return false;	
}


