#include<iostream>
#include<cstdlib>



#include "nlsr.hpp"
#include "nlsr_im.hpp"
#include "nlsr_dm.hpp"
#include "nlsr_tokenizer.hpp"
#include "nlsr_lsdb.hpp"

namespace nlsr
{

    using namespace std;
    using namespace ndn;

    void
    interestManager::processInterest( Nlsr& pnlsr,
                                      const ndn::Name &name,
                                      const ndn::Interest &interest)
    {

        cout << "<< I: " << interest << endl;
        string intName=interest.getName().toUri();
        cout << "Interest Received for Name: "<< intName <<endl;
        nlsrTokenizer nt(intName,"/");
        string chkString("info");
        if( nt.doesTokenExist(chkString) )
        {
            string nbr=nt.getTokenString(nt.getTokenPosition(chkString)+1);
            cout <<"Neighbor: " << nbr <<endl;
            processInterestInfo(pnlsr,nbr,interest);
        }

        //Data data(ndn::Name(interest->getName()).append("testApp").appendVersion());
        //data.setFreshnessPeriod(1000); // 10 sec
        //data.setContent((const uint8_t*)"HELLO KITTY", sizeof("HELLO KITTY"));
        //pnlsr.getKeyChain().sign(data);
        //cout << ">> D: " << data << endl;
        //pnlsr.getNlsrFace().put(data);
    }

    void
    interestManager::processInterestInfo(Nlsr& pnlsr, string& neighbor,
                                         const ndn::Interest &interest)
    {
        if ( pnlsr.getAdl().isNeighbor(neighbor) )
        {
            Data data(ndn::Name(interest.getName()).appendVersion());
            data.setFreshnessPeriod(1000); // 10 sec
            data.setContent((const uint8_t*)"info", sizeof("info"));
            pnlsr.getKeyChain().sign(data);
            cout << ">> D: " << data << endl;
            pnlsr.getNlsrFace().put(data);

            int status=pnlsr.getAdl().getStatusOfNeighbor(neighbor);
            if ( status == 0 )
            {
                string intName=neighbor +"/"+"info"+
                               pnlsr.getConfParameter().getRouterPrefix();
                expressInterest(	pnlsr,intName,2,
                                    pnlsr.getConfParameter().getInterestResendTime());
            }
        }
    }

    void
    interestManager::processInterestTimedOut(Nlsr& pnlsr,
            const ndn::Interest &interest)
    {
        cout << "Timed out interest : " << interest.getName().toUri() << endl;
        string intName=	interest.getName().toUri();
        nlsrTokenizer nt(intName,"/");
        string chkString("info");
        if( nt.doesTokenExist(chkString) )
        {
            string nbr="/" + nt.getFirstToken()
                       +nt.getTokenString(0,nt.getTokenPosition(chkString)-1);
            processInterestTimedOutInfo( pnlsr , nbr , interest);
        }

    }

    void
    interestManager::processInterestTimedOutInfo(Nlsr& pnlsr, string& neighbor,
            const ndn::Interest &interest)
    {
        pnlsr.getAdl().incrementTimedOutInterestCount(neighbor);
        int status=pnlsr.getAdl().getStatusOfNeighbor(neighbor);
        int infoIntTimedOutCount=pnlsr.getAdl().getTimedOutInterestCount(neighbor);
        cout<<"Neighbor: "<< neighbor << endl;
        cout<<"Status: "<< status << endl;
        cout<<"Info Interest Timed out: "<< infoIntTimedOutCount <<endl;

        if((infoIntTimedOutCount < pnlsr.getConfParameter().getInterestRetryNumber()))
        {
            string intName=neighbor +"/"+"info"+
                           pnlsr.getConfParameter().getRouterPrefix();
            expressInterest(	pnlsr,intName,2,
                                pnlsr.getConfParameter().getInterestResendTime());
        }
        else if ( (status == 1) &&
                  (infoIntTimedOutCount == pnlsr.getConfParameter().getInterestRetryNumber()))
        {
            pnlsr.getAdl().setStatusOfNeighbor(neighbor,0);
            pnlsr.incrementAdjBuildCount();
            if ( pnlsr.getIsBuildAdjLsaSheduled() == 0 )
            {
                pnlsr.setIsBuildAdjLsaSheduled(1);
                // event here
                pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(5),
                                                   ndn::bind(&Lsdb::scheduledAdjLsaBuild,pnlsr.getLsdb(),
                                                           boost::ref(pnlsr)));
            }
        }

    }

    void
    interestManager::expressInterest(Nlsr& pnlsr,const string& interestNamePrefix,
                                     int scope, int seconds)
    {
        Interest i((ndn::Name(interestNamePrefix)));
        //i.setScope(scope);
        i.setInterestLifetime(seconds*1000);
        i.setMustBeFresh(true);

        pnlsr.getNlsrFace().expressInterest(i,
                                            ndn::func_lib::bind(&DataManager::processContent,
                                                    &pnlsr.getDm(), boost::ref(pnlsr),_1, _2),
                                            ndn::func_lib::bind(&interestManager::processInterestTimedOut,
                                                    this,boost::ref(pnlsr),_1));
    }


    void
    interestManager::sendScheduledInfoInterest(Nlsr& pnlsr, int seconds)
    {
        std::list<Adjacent> adjList=pnlsr.getAdl().getAdjList();
        for(std::list<Adjacent>::iterator it=adjList.begin(); it!=adjList.end(); ++it)
        {
            string adjName=(*it).getAdjacentName()+"/"+"info"+
                           pnlsr.getConfParameter().getRouterPrefix();
            expressInterest(	pnlsr,adjName,2,
                                pnlsr.getConfParameter().getInterestResendTime());
        }

        scheduleInfoInterest(pnlsr, pnlsr.getConfParameter().getInfoInterestInterval());

    }

    void
    interestManager::scheduleInfoInterest(Nlsr& pnlsr, int seconds)
    {
        EventId eid=pnlsr.getScheduler().scheduleEvent(ndn::time::seconds(seconds),
                    ndn::bind(&interestManager::sendScheduledInfoInterest, this,
                              boost::ref(pnlsr),seconds));
    }


} //namespace nlsr
