#include "nlsr.hpp"
#include "nlsr_slh.hpp"
#include "security/nlsr_km.hpp"
#include "utility/nlsr_tokenizer.hpp"


namespace nlsr
{
  void
  SyncLogicHandler::createSyncSocket(Nlsr &pnlsr )
  {
    cout<<"Creating Sync socket ......"<<endl;
    cout<<"Sync prefix: "<<syncPrefix.toUri()<<endl;
    syncSocket=make_shared<SyncSocket>(syncPrefix, validator, syncFace,
                                       bind(&SyncLogicHandler::nsyncUpdateCallBack,this,
                                            _1, _2,boost::ref(pnlsr)),
                                       bind(&SyncLogicHandler::nsyncRemoveCallBack, this,
                                            _1,boost::ref(pnlsr)));
  }

  void
  SyncLogicHandler::nsyncUpdateCallBack(const vector<MissingDataInfo> &v,
                                        SyncSocket *socket, Nlsr& pnlsr)
  {
    cout<<"nsyncUpdateCallBack called ...."<<endl;
    int n = v.size();
    for(int i=0; i < n; i++)
    {
      std::cout<<"Data Name: "<<v[i].prefix<<" Seq: "<<v[i].high.getSeq()<<endl;
      processUpdateFromSync(v[i].prefix,v[i].high.getSeq(),pnlsr);
    }
  }

  void
  SyncLogicHandler::nsyncRemoveCallBack(const string& prefix, Nlsr& pnlsr)
  {
    cout<<"nsyncRemoveCallBack called ...."<<endl;
  }

  void
  SyncLogicHandler::removeRouterFromSyncing(string& routerPrefix)
  {
  }

  void
  SyncLogicHandler::processUpdateFromSync(std::string updateName,
                                          uint64_t seqNo,  Nlsr& pnlsr)
  {
    nlsrTokenizer nt(updateName,"/");
    string chkString("LSA");
    if( nt.doesTokenExist(chkString) )
    {
      //process LSA Update here
      string routerName=nt.getTokenString(nt.getTokenPosition(chkString)+1);
      processRoutingUpdateFromSync(routerName, seqNo, pnlsr);
    }
    chkString="keys";
    if( nt.doesTokenExist(chkString) )
    {
      //process keys update here
      std::string certName=nt.getTokenString(0);
      processKeysUpdateFromSync(certName,seqNo, pnlsr);
    }
  }

  void
  SyncLogicHandler::processRoutingUpdateFromSync(std::string routerName,
      uint64_t seqNo,  Nlsr& pnlsr)
  {
    if( routerName != pnlsr.getConfParameter().getRouterPrefix() )
    {
      SequencingManager sm(seqNo);
      cout<<sm;
      cout<<"Router Name: "<<routerName<<endl;
      if ( pnlsr.getLsdb().isNameLsaNew(routerName+"/1",sm.getNameLsaSeq()))
      {
        cout<<"Updated Name LSA. Need to fetch it"<<endl;
        string lsaPrefix=
          pnlsr.getConfParameter().getChronosyncLsaPrefix() +
          routerName + "/1/" +
          boost::lexical_cast<std::string>(sm.getNameLsaSeq());
        pnlsr.getIm().expressInterest(pnlsr, lsaPrefix, 3,
                                      pnlsr.getConfParameter().getInterestResendTime());
      }
      if ( pnlsr.getLsdb().isAdjLsaNew(routerName+"/2",sm.getAdjLsaSeq()))
      {
        cout<<"Updated Adj LSA. Need to fetch it"<<endl;
        string lsaPrefix=
          pnlsr.getConfParameter().getChronosyncLsaPrefix() +
          routerName + "/2/" +
          boost::lexical_cast<std::string>(sm.getAdjLsaSeq());
        pnlsr.getIm().expressInterest(pnlsr, lsaPrefix, 3,
                                      pnlsr.getConfParameter().getInterestResendTime());
      }
      if ( pnlsr.getLsdb().isCorLsaNew(routerName+"/3",sm.getCorLsaSeq()))
      {
        cout<<"Updated Cor LSA. Need to fetch it"<<endl;
        string lsaPrefix=
          pnlsr.getConfParameter().getChronosyncLsaPrefix() +
          routerName + "/3/" +
          boost::lexical_cast<std::string>(sm.getCorLsaSeq());
        pnlsr.getIm().expressInterest(pnlsr, lsaPrefix, 3,
                                      pnlsr.getConfParameter().getInterestResendTime());
      }
    }
  }

  void
  SyncLogicHandler::processKeysUpdateFromSync(std::string certName,
      uint64_t seqNo, Nlsr& pnlsr)
  {
    cout<<"Cert Name: "<<certName<<std::endl;
    if ( pnlsr.getKeyManager().isNewCertificate(certName,seqNo) )
    {
      string certNamePrefix=certName + "/" +
                            boost::lexical_cast<string>(seqNo);
      pnlsr.getIm().expressInterest(pnlsr, certNamePrefix, 3,
                                    pnlsr.getConfParameter().getInterestResendTime());
    }
  }

  void
  SyncLogicHandler::publishRoutingUpdate(SequencingManager& sm,
                                         string updatePrefix)
  {
    sm.writeSeqNoToFile();
    publishSyncUpdate(updatePrefix,sm.getCombinedSeqNo());
  }

  void
  SyncLogicHandler::publishKeyUpdate(KeyManager& km)
  {
    //publishSyncUpdate(km.getRootCertName().toUri(), 10);
    //publishSyncUpdate(km.getSiteCertName().toUri(), 10);
    //publishSyncUpdate(km.getOperatorCertName().toUri(), 10);
    //publishSyncUpdate(km.getRouterCertName().toUri(), km.getCertSeqNo());
    publishSyncUpdate(km.getProcessCertName().toUri(),km.getCertSeqNo());
  }

  void
  SyncLogicHandler::publishIdentityUpdate(string identityName)
  {
    publishSyncUpdate(identityName,0);
  }

  void
  SyncLogicHandler::publishSyncUpdate(string updatePrefix, uint64_t seqNo)
  {
    cout<<"Publishing Sync Update ......"<<endl;
    cout<<"Update in prefix: "<<updatePrefix<<endl;
    cout<<"Seq No: "<<seqNo<<endl;
    ndn::Name updateName(updatePrefix);
    string data("NoData");
    syncSocket->publishData(updateName,0,data.c_str(),data.size(),1000,seqNo);
  }

}
