#include <ndn-cpp-dev/security/identity-certificate.hpp>
#include <ndn-cpp-dev/encoding/block.hpp>
#include <ndn-cpp-dev/util/io.hpp>
#include <stdexcept>
#include "nlsr_sm.hpp"
#include "nlsr_km.hpp"
#include "nlsr.hpp"

#define THIS_FILE "nlsr_km.cpp"

namespace nlsr
{
  bool
  KeyManager::initialize(ConfParameter &cp)
  {
    initCertSeqFromFile(cp.getSeqFileDir());
    if( !loadAllCertificates(cp.getCertDir()) )
    {
      return false;
    }
    m_nlsrRootKeyPrefix=cp.getRootKeyPrefix();
    string processIdentityName(cp.getRootKeyPrefix());
    processIdentityName += "/";
    processIdentityName += cp.getSiteName();
    processIdentityName += "/";
    processIdentityName += "R.Start";
    processIdentityName += "/";
    processIdentityName += cp.getRouterName();
    ndn::Name ri(processIdentityName);
    std::cout<<"Router Identity: "<<ri.toUri()<<std::endl;
    m_routerIdentity=ri;
    processIdentityName += "/";
    processIdentityName += "nlsr";
    cout<<"Proces Identity Name: "<<processIdentityName<<endl;
    ndn::Name identityName(processIdentityName);
    m_processIdentity=identityName;
    ndn::KeyChain::deleteIdentity(m_processIdentity);
    m_processCertName = ndn::KeyChain::createIdentity(m_processIdentity);
    cout<<"Certificate Name: "<<m_processCertName.toUri()<<endl;
    m_processKeyName=m_processCertName.getPrefix(-2);
    cout<<"Key Name: "<<m_processKeyName.toUri()<<endl;
    ndn::shared_ptr<ndn::IdentityCertificate> cert = 
                                                getCertificate(m_processCertName);
    signByIdentity(*(cert),m_routerIdentity);
    m_certStore.addCertificate(cert, m_certSeqNo, true);
    m_certStore.print();
    return true;
  }

  bool
  KeyManager::loadAllCertificates(std::string certDirPath)
  {
    std::string filePath=certDirPath;
    if(filePath.empty())
    {
      SequencingManager sm;
      filePath=sm.getUserHomeDirectory();
      filePath+="/nlsrCertDir";
    }
    return loadCertificate(filePath+"/root.cert", KEY_TYPE_ROOT)
           && loadCertificate(filePath+"/site.cert", KEY_TYPE_SITE)
           && loadCertificate(filePath+"/operator.cert", KEY_TYPE_OPERATOR)
           && loadCertificate(filePath+"/router.cert", KEY_TYPE_ROUTER) ;
  }

  bool
  KeyManager::loadCertificate(std::string inputFile, nlsrKeyType keyType)
  {
    try
    {
      ndn::shared_ptr<ndn::IdentityCertificate> cert =
        ndn::io::load<ndn::IdentityCertificate>(inputFile, ndn::io::BASE_64);
      ndn::Name certName=cert->getName();
      switch(keyType)
        {
        case KEY_TYPE_ROOT:
          m_certStore.addCertificate(cert, 10, true);
          m_rootCertName=certName;
          std::cout<<"Root Cert: "<<m_rootCertName<<std::endl;
          break;
        case KEY_TYPE_SITE:
          m_certStore.addCertificate(cert, 10, true);
          m_siteCertName=certName;
          std::cout<<"Site Cert: "<<m_siteCertName<<std::endl;
          break;
        case KEY_TYPE_OPERATOR:
          m_certStore.addCertificate(cert, 10, true);
          m_opCertName=certName;
          std::cout<<"Operator Cert: "<<m_opCertName<<std::endl;
          break;
        case KEY_TYPE_ROUTER:
          m_certStore.addCertificate(cert, m_certSeqNo, true);
          m_routerCertName=certName;
          std::cout<<"Router Cert: "<<m_routerCertName<<std::endl;
          break;
        case KEY_TYPE_PROCESS:
          m_certStore.addCertificate(cert, m_certSeqNo, true);
          m_processCertName=certName;
          std::cout<<"Process Cert: "<<m_processCertName<<std::endl;
          break;
        default:
          break;
        }
      return true;
    }
    catch(std::exception& e)
    {
      return false;
    }
    return false;
  }

  ndn::Name
  KeyManager::getProcessCertName()
  {
    return m_processCertName;
  }

  ndn::Name
  KeyManager::getRouterCertName()
  {
    return m_routerCertName;
  }

  ndn::Name
  KeyManager::getOperatorCertName()
  {
    return m_opCertName;
  }

  ndn::Name
  KeyManager::getSiteCertName()
  {
    return m_siteCertName;
  }

  ndn::Name
  KeyManager::getRootCertName()
  {
    return m_rootCertName;
  }

  uint32_t
  KeyManager::getCertSeqNo()
  {
    return m_certSeqNo;
  }

  void
  KeyManager::setCerSeqNo(uint32_t csn)
  {
    m_certSeqNo=csn;
  }

  void
  KeyManager::initCertSeqFromFile(string certSeqFileDir)
  {
    m_certSeqFileNameWithPath=certSeqFileDir;
    if( m_certSeqFileNameWithPath.empty() )
    {
      SequencingManager sm;
      m_certSeqFileNameWithPath=sm.getUserHomeDirectory();
    }
    m_certSeqFileNameWithPath += "/nlsrCertSeqNo.txt";
    cout<<"Key Seq File Name: "<< m_certSeqFileNameWithPath<<endl;
    std::ifstream inputFile(m_certSeqFileNameWithPath.c_str(),ios::binary);
    if ( inputFile.good() )
    {
      inputFile>>m_certSeqNo;
      m_certSeqNo++;
    }
    else
    {
      m_certSeqNo=1;
    }
    writeCertSeqToFile();
  }

  void
  KeyManager::writeCertSeqToFile()
  {
    std::ofstream outputFile(m_certSeqFileNameWithPath.c_str(),ios::binary);
    outputFile<<m_certSeqNo;
    outputFile.close();
  }

  bool
  KeyManager::isNewCertificate(std::string certName, int checkSeqNum)
  {
    return m_certStore.isCertificateNewInStore(certName,checkSeqNum);
  }

  std::pair<ndn::shared_ptr<ndn::IdentityCertificate>, bool>
  KeyManager::getCertificateFromStore(const std::string certName, int checkSeqNum)
  {
    return m_certStore.getCertificateFromStore(certName, checkSeqNum);
  }

  std::pair<ndn::shared_ptr<ndn::IdentityCertificate>, bool>
  KeyManager::getCertificateFromStore(const std::string certName)
  {
    return m_certStore.getCertificateFromStore(certName);
  }

  bool
  KeyManager::addCertificate(ndn::shared_ptr<ndn::IdentityCertificate> pcert
                             , uint32_t csn, bool isv)
  {
    return m_certStore.addCertificate(pcert, csn, isv);
  }
  
  std::pair<uint32_t, bool> 
  KeyManager::getCertificateSeqNum(std::string certName)
  {
    return m_certStore.getCertificateSeqNum(certName);
  }

  nlsrKeyType
  KeyManager::getKeyTypeFromName(const std::string keyName)
  {
    nlsrTokenizer nt(keyName,"/");
    std::string KEY("KEY");
    std::string opHandle("O.Start");
    std::string routerHandle("R.Start");
    std::string processHandle("nlsr");
    if ( nt.getTokenString(0,nt.getTokenPosition(KEY)-1) == m_nlsrRootKeyPrefix)
    {
      return KEY_TYPE_ROOT;
    }
    else if ( nt.doesTokenExist(opHandle) )
    {
      return KEY_TYPE_OPERATOR;
    }
    else if ( nt.doesTokenExist(routerHandle) &&
              nt.doesTokenExist(processHandle))
    {
      return KEY_TYPE_PROCESS;
    }
    else if ( nt.doesTokenExist(routerHandle) &&
              !nt.doesTokenExist(processHandle))
    {
      return KEY_TYPE_ROUTER;
    }
    else
    {
      return KEY_TYPE_SITE;
    }
  }

  std::string
  KeyManager::getRouterName(const std::string name)
  {
    std::string routerName;
    std::string rkp(m_nlsrRootKeyPrefix);
    nlsrTokenizer ntRkp(rkp,"/");
    nlsrTokenizer nt(name,"/");
    std::string KEY("KEY");
    std::string opHandle("O.Start");
    std::string routerHandle("R.Start");
    std::string processHandle("nlsr");
    std::string infoHandle("info");
    std::string lsaHandle("LSA");
    if ( nt.doesTokenExist(processHandle) && nt.doesTokenExist(routerHandle))
    {
      routerName="/ndn" +
                 nt.getTokenString(ntRkp.getTokenNumber(),
                                   nt.getTokenPosition(routerHandle)-1) +
                 nt.getTokenString(nt.getTokenPosition(routerHandle)+1,
                                   nt.getTokenPosition(processHandle)-1);
    }
    else if(nt.doesTokenExist(routerHandle) && !nt.doesTokenExist(infoHandle)
            && !nt.doesTokenExist(lsaHandle))
    {
      routerName="/ndn" +
                 nt.getTokenString(ntRkp.getTokenNumber(),
                                   nt.getTokenPosition(routerHandle)-1) +
                 nt.getTokenString(nt.getTokenPosition(routerHandle)+1,
                                   nt.getTokenPosition(KEY)-1);
    }
    else
    {
      if (nt.doesTokenExist(infoHandle) )
      {
        routerName=nt.getTokenString(0,nt.getTokenPosition(infoHandle)-1);
      }
      else
      {
        routerName=nt.getTokenString(nt.getTokenPosition(lsaHandle)+1,
                                     nt.getTokenNumber()-4);
      }
    }
    return routerName;
  }

  std::string
  KeyManager::getSiteName(const std::string name)
  {
    std::string siteName;
    std::string routerName;
    std::string rkp(m_nlsrRootKeyPrefix);
    nlsrTokenizer ntRkp(rkp,"/");
    nlsrTokenizer nt(name,"/");
    std::string KEY("KEY");
    std::string opHandle("O.Start");
    std::string routerHandle("R.Start");
    if ( nt.doesTokenExist(routerHandle) )
    {
      siteName="/ndn" + nt.getTokenString(ntRkp.getTokenNumber(),
                                          nt.getTokenPosition(routerHandle) -1);
    }
    else if ( nt.doesTokenExist(opHandle) )
    {
      siteName="/ndn" + nt.getTokenString(ntRkp.getTokenNumber(),
                                          nt.getTokenPosition(opHandle) -1);
    }
    else
    {
      siteName="/ndn" + nt.getTokenString(ntRkp.getTokenNumber(),
                                          nt.getTokenPosition(KEY) -1);
    }
    return siteName;
  }
  
  std::string 
  KeyManager::getRootName(const std::string name)
  {
    std::string rName;
    nlsrTokenizer nt(name,"/");
    std::string rkp(m_nlsrRootKeyPrefix);
    nlsrTokenizer ntRkp(rkp,"/");
    rName=nt.getTokenString(0,ntRkp.getTokenNumber()-1);
    return rName;
  }
  
  
  bool
  KeyManager::verifyCertPacket(Nlsr& pnlsr, ndn::IdentityCertificate& packet)
    {
      std::cout<<"KeyManager::verifyCertPacket Called"<<std::endl;
      ndn::SignatureSha256WithRsa signature(packet.getSignature());
      std::string signingCertName=signature.getKeyLocator().getName().toUri();
      std::string packetName=packet.getName().toUri();
      
      std::cout<<"Packet Name: "<<packetName<<std::endl;
      std::cout<<"Signee Name: "<<signingCertName<<std::endl;
      
      int paketCertType=getKeyTypeFromName(packetName);
      int signingCertType=getKeyTypeFromName(signingCertName);
      
      if( signingCertType > paketCertType ) //lower level Cert can not sign
      {                                     //upper level Cert
        return false;
      }
      
      if((signingCertType == paketCertType) && (paketCertType != KEY_TYPE_ROOT))
      {
        return false;
      }
      
      std::pair<ndn::shared_ptr<ndn::IdentityCertificate>, bool> signee=
                             m_certStore.getCertificateFromStore(signingCertName);
      
      if( signee.second )
      {
        switch(paketCertType)
          {
          case KEY_TYPE_ROOT:
            return ((getRootName(packetName) == m_nlsrRootKeyPrefix) &&
                     verifySignature(packet,signee.first->getPublicKeyInfo()));
            break;
          case KEY_TYPE_SITE:
            return ((getRootName(packetName) == getRootName(signingCertName)) &&
                      verifySignature(packet,signee.first->getPublicKeyInfo()) &&
                      m_certStore.getCertificateIsVerified(signingCertName));                   
            break;
          case KEY_TYPE_OPERATOR:
            return ((getSiteName(packetName) == getSiteName(signingCertName)) &&
                     verifySignature(packet,signee.first->getPublicKeyInfo()) &&
                     m_certStore.getCertificateIsVerified(signingCertName)); 
            break;
          case KEY_TYPE_ROUTER:
            return ((getSiteName(packetName) == getSiteName(signingCertName)) &&
                     verifySignature(packet,signee.first->getPublicKeyInfo()) &&
                     m_certStore.getCertificateIsVerified(signingCertName));
            break;
          case KEY_TYPE_PROCESS:
            return ((getRouterName(packetName) == getRouterName(signingCertName)) &&
                     verifySignature(packet,signee.first->getPublicKeyInfo()) &&
                     m_certStore.getCertificateIsVerified(signingCertName));
            break;
          }
      }
      else
      {
        std::cout<<"Certificate Not Found in store. Sending Interest"<<std::endl;
        pnlsr.getIm().expressInterest(pnlsr, signingCertName, 3,
                              pnlsr.getConfParameter().getInterestResendTime());
        return false;
      }
      return false;
    }
}



