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

namespace nlsr
{

    using namespace std;

    void
    RoutingTable::calculate(Nlsr& pnlsr)
    {
        //debugging purpose
        pnlsr.getNpt().printNpt();
        pnlsr.getLsdb().printAdjLsdb();
        pnlsr.getLsdb().printCorLsdb();
        pnlsr.getLsdb().printNameLsdb();
        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
                std::cout<<"Calling Update NPT With new Route"<<std::endl;
                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
        {
            scheduleRoutingTableCalculation(pnlsr);
        }
    }


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

    void
    RoutingTable::scheduleRoutingTableCalculation(Nlsr& pnlsr)
    {
        if ( pnlsr.getIsRouteCalculationScheduled() != 1 )
        {
            pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(15),
                                               ndn::bind(&RoutingTable::calculate,this,boost::ref(pnlsr)));
            pnlsr.setIsRouteCalculationScheduled(1);
        }
    }

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

}//namespace nlsr

