#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"

using namespace std;

void
RoutingTable::calculate(nlsr& pnlsr)
{

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

		printRoutingTable();

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

