#include<iostream>
#include<string>
#include<list>

#include "nlsr_rt.hpp"
#include "nlsr.hpp"
#include "nlsr_map.hpp"
#include "nlsr_rtc.hpp"
#include "nlsr_rte.hpp"
#include "nlsr_npt.hpp"

using namespace std;

void
RoutingTable::calculate(nlsr& pnlsr)
{
	//debugging purpose
	pnlsr.getNpt().printNpt();

	if ( 	pnlsr.getIsRoutingTableCalculating() == 0 )
	{
		pnlsr.setIsRoutingTableCalculating(1); //setting routing table calculation
		
		if ( pnlsr.getLsdb().doesLsaExist(
						pnlsr.getConfParameter().getRouterPrefix()+"/"+"2",2) )
		{
			if(pnlsr.getIsBuildAdjLsaSheduled() != 1)
			{
				cout<<"CLearing old routing table ....."<<endl;
				clearRoutingTable();
				clearDryRoutingTable(); // for dry run options
				// calculate Link State routing
				if( (pnlsr.getConfParameter().getIsHyperbolicCalc() == 0 ) 
						|| (pnlsr.getConfParameter().getIsHyperbolicCalc() == 2 ) )
				{
					calculateLsRoutingTable(pnlsr);
				}
				//calculate hyperbolic routing
				if ( pnlsr.getConfParameter().getIsHyperbolicCalc() == 1 )
				{
					calculateHypRoutingTable(pnlsr);
				}
				//calculate dry hyperbolic routing
				if ( pnlsr.getConfParameter().getIsHyperbolicCalc() == 2 )
				{
					calculateHypDryRoutingTable(pnlsr);
				}

				//need to update NPT here
				pnlsr.getNpt().updateNptWithNewRoute(pnlsr);
				//debugging purpose
				printRoutingTable();
				pnlsr.getNpt().printNpt();
				pnlsr.getFib().printFib();
				//debugging purpose end
			}
			else
			{
				cout<<"Adjacency building is scheduled, so ";
				cout<<"routing table can not be calculated :("<<endl;
			}
		}
		else
		{
			cout<<"No Adj LSA of router itself,";
			cout<<	" so Routing table can not be calculated :("<<endl;	
			clearRoutingTable();
		  clearDryRoutingTable(); // for dry run options
		  // need to update NPT here
		  pnlsr.getNpt().updateNptWithNewRoute(pnlsr);
		  //debugging purpose
		  	printRoutingTable();
			pnlsr.getNpt().printNpt();
			pnlsr.getFib().printFib();
			//debugging purpose end
		}


		pnlsr.setIsRouteCalculationScheduled(0); //clear scheduled flag
		pnlsr.setIsRoutingTableCalculating(0); //unsetting routing table calculation
	}
	else
	{
		pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(15),
									 ndn::bind(&RoutingTable::calculate,this,boost::ref(pnlsr)));
		pnlsr.setIsRouteCalculationScheduled(1);
	}

}


void 
RoutingTable::calculateLsRoutingTable(nlsr& pnlsr)
{
	cout<<"RoutingTable::calculateLsRoutingTable Called"<<endl;
	Map vMap;
	vMap.createMapFromAdjLsdb(pnlsr);
	int numOfRouter=vMap.getMapSize();

	LinkStateRoutingTableCalculator lsrtc(numOfRouter);
	lsrtc.calculatePath(vMap,boost::ref(*this),pnlsr);
}

void 
RoutingTable::calculateHypRoutingTable(nlsr& pnlsr)
{
	Map vMap;
	vMap.createMapFromAdjLsdb(pnlsr);
	int numOfRouter=vMap.getMapSize();
	HypRoutingTableCalculator hrtc(numOfRouter,0);
	hrtc.calculatePath(vMap,boost::ref(*this),pnlsr);
}

void 
RoutingTable::calculateHypDryRoutingTable(nlsr& pnlsr)
{
	Map vMap;
	vMap.createMapFromAdjLsdb(pnlsr);
	int numOfRouter=vMap.getMapSize();
	HypRoutingTableCalculator hrtc(numOfRouter,1);
	hrtc.calculatePath(vMap,boost::ref(*this),pnlsr);
}

static bool
routingTableEntryCompare(RoutingTableEntry& rte, string& destRouter){
	return rte.getDestination()==destRouter;
}

// function related to manipulation of routing table
void 
RoutingTable::addNextHop(string destRouter, NextHop& nh)
{
	std::pair<RoutingTableEntry&, bool> rte=findRoutingTableEntry(destRouter);
	if( !rte.second )
	{
		RoutingTableEntry rte(destRouter);
		rte.getNhl().addNextHop(nh);
		rTable.push_back(rte);
	}
	else
	{
		(rte.first).getNhl().addNextHop(nh);
	}
}

std::pair<RoutingTableEntry&, bool> 
RoutingTable::findRoutingTableEntry(string destRouter)
{
	std::list<RoutingTableEntry >::iterator it = std::find_if( rTable.begin(), 
									rTable.end(),	
   								bind(&routingTableEntryCompare, _1, destRouter));
  if ( it != rTable.end() )
  {
  		return std::make_pair(boost::ref((*it)),true);
  }
  RoutingTableEntry rteEmpty;
  return std::make_pair(boost::ref(rteEmpty),false);
}

void
RoutingTable::printRoutingTable()
{
	cout<<"---------------Routing Table------------------"<<endl;
	for(std::list<RoutingTableEntry>::iterator it=rTable.begin() ;
															                       it != rTable.end(); ++it)
	{
			cout<<(*it)<<endl;
	}
}


//function related to manipulation of dry routing table
void 
RoutingTable::addNextHopToDryTable(string destRouter, NextHop& nh)
{
	std::list<RoutingTableEntry >::iterator it = std::find_if( dryTable.begin(), 
									dryTable.end(),	
   								bind(&routingTableEntryCompare, _1, destRouter));
	if ( it == dryTable.end() ){
		RoutingTableEntry rte(destRouter);
		rte.getNhl().addNextHop(nh);
		dryTable.push_back(rte);
	}	
	else
	{
		(*it).getNhl().addNextHop(nh);
	}
	
}

void
RoutingTable::printDryRoutingTable()
{
	cout<<"--------Dry Run's Routing Table--------------"<<endl;
	for(std::list<RoutingTableEntry>::iterator it=dryTable.begin() ;
															                      it != dryTable.end(); ++it)
	{
		cout<<(*it)<<endl;
	}
}


void 
RoutingTable::clearRoutingTable()
{
	if( rTable.size() > 0 )
	{
		rTable.clear();
	}
}

void 
RoutingTable::clearDryRoutingTable()
{
	if (dryTable.size()>0 )
	{
		dryTable.clear();
	}
}

