/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013, Regents of the University of California
 *                     Yingdi Yu
 *
 * BSD license, See the LICENSE file for more information
 *
 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
 */

#include "sync-intro-certificate.h"
#include "sync-logging.h"
#include <ndn-cpp-dev/security/verifier.hpp>
#include <ndn-cpp-dev/security/signature-sha256-with-rsa.hpp>

#include "sec-policy-sync.h"

using namespace ndn;
using namespace ndn::ptr_lib;
using namespace std;

INIT_LOGGER("SecPolicySync");

SecPolicySync::SecPolicySync(const Name& signingIdentity,
				     const Name& signingCertificateName,
				     const Name& syncPrefix,
                                     shared_ptr<Face> face,
                                     int stepLimit)
  : m_signingIdentity(signingIdentity)
  , m_signingCertificateName(signingCertificateName.getPrefix(signingCertificateName.size()-1))
  , m_syncPrefix(syncPrefix)
  , m_stepLimit(stepLimit)
  , m_keyChain(new KeyChain())
{  
  Name wotPrefix = syncPrefix;
  wotPrefix.append("WOT");
  m_syncPrefixRegex = Regex::fromName(syncPrefix);
  m_wotPrefixRegex = Regex::fromName(wotPrefix);
  m_chatDataPolicy = make_shared<SecRuleIdentity>("^[^<%F0.>]*<%F0.>([^<chronos>]*)<chronos><>",
                                                  "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
                                                  "==", "\\1", "\\1", true);  
}
  
SecPolicySync::~SecPolicySync()
{}

bool 
SecPolicySync::skipVerifyAndTrust (const Data& data)
{ return false; }

bool
SecPolicySync::requireVerify (const Data& data)
{ return true; }

shared_ptr<ValidationRequest>
SecPolicySync::checkVerificationPolicy(const shared_ptr<Data>& data, 
					   int stepCount, 
					   const OnVerified& onVerified,
					   const OnVerifyFailed& onVerifyFailed)
{
  if(stepCount > m_stepLimit)
    {
      onVerifyFailed(data);
      return shared_ptr<ValidationRequest>();
    }

  try{
    SignatureSha256WithRsa sig(data->getSignature());

    const Name& keyLocatorName = sig.getKeyLocator().getName();
  
    // if data is intro cert
    if(m_wotPrefixRegex->match(data->getName()))
      {
        // _LOG_DEBUG("Intro Cert");
        Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
        map<string, PublicKey>::const_iterator it = m_trustedIntroducers.find(keyName.toUri());
        if(m_trustedIntroducers.end() != it)
          {
            if(Verifier::verifySignature(*data, sig, it->second))
              onVerified(data);
            else
              onVerifyFailed(data);
            return shared_ptr<ValidationRequest>();
          }
        else
          return prepareRequest(keyName, true, data, stepCount, onVerified, onVerifyFailed);
      }

    // if data is sync data or chat data
    if(m_syncPrefixRegex->match(data->getName()) || m_chatDataPolicy->satisfy(*data))
      {
        Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);

        map<string, PublicKey>::const_iterator it = m_trustedIntroducers.find(keyName.toUri());
        if(m_trustedIntroducers.end() != it)
          {
            if(Verifier::verifySignature(*data, sig, it->second))
              onVerified(data);
            else
              onVerifyFailed(data);
            return shared_ptr<ValidationRequest>();
          }

        it = m_trustedProducers.find(keyName.toUri());
        if(m_trustedProducers.end() != it)
          {
            if(Verifier::verifySignature(*data, sig, it->second))
              onVerified(data);
            else
              onVerifyFailed(data);
            return shared_ptr<ValidationRequest>();
          }

        return prepareRequest(keyName, false, data, stepCount, onVerified, onVerifyFailed);
      }
  }catch(SignatureSha256WithRsa::Error &e){
    _LOG_DEBUG("SecPolicySync Error: " << e.what());
    onVerifyFailed(data);
    return shared_ptr<ValidationRequest>();
  }catch(KeyLocator::Error &e){
    _LOG_DEBUG("SecPolicySync Error: " << e.what());
    onVerifyFailed(data);
    return shared_ptr<ValidationRequest>();
  }
    
  onVerifyFailed(data);
  return shared_ptr<ValidationRequest>();
}

bool 
SecPolicySync::checkSigningPolicy(const Name& dataName, 
				      const Name& certificateName)
{ 
  return true;
}
    
Name 
SecPolicySync::inferSigningIdentity(const ndn::Name& dataName)
{ return m_signingIdentity; }

void
SecPolicySync::addTrustAnchor(const IdentityCertificate& identityCertificate, bool isIntroducer)
{
  // _LOG_DEBUG("Add intro/producer: " << identityCertificate.getPublicKeyName());
  if(isIntroducer)
    m_trustedIntroducers.insert(pair <string, PublicKey > (identityCertificate.getPublicKeyName().toUri(),
                                                           identityCertificate.getPublicKeyInfo()));
  else
    m_trustedProducers.insert(pair <string, PublicKey > (identityCertificate.getPublicKeyName().toUri(),
                                                         identityCertificate.getPublicKeyInfo()));
}

void
SecPolicySync::addChatDataRule(const Name& prefix, 
                                   const IdentityCertificate& identityCertificate,
                                   bool isIntroducer)
{
  addTrustAnchor(identityCertificate, isIntroducer);
}


shared_ptr<const vector<Name> >
SecPolicySync::getAllIntroducerName()
{
  shared_ptr<vector<Name> > nameList = make_shared<vector<Name> >();
  
  map<string, PublicKey>::iterator it =  m_trustedIntroducers.begin();
  for(; it != m_trustedIntroducers.end(); it++)
    nameList->push_back(Name(it->first));
  
  return nameList;
}

shared_ptr<ValidationRequest>
SecPolicySync::prepareRequest(const Name& keyName, 
				  bool forIntroducer,
				  shared_ptr<Data> data,
				  const int & stepCount, 
				  const OnVerified& onVerified,
				  const OnVerifyFailed& onVerifyFailed)
{
  shared_ptr<Name> interestPrefixName = make_shared<Name>(m_syncPrefix);
  interestPrefixName->append("WOT").append(keyName).append("INTRO-CERT");

  shared_ptr<const vector<Name> > nameList = getAllIntroducerName();
  if(0 == nameList->size())
    {
      onVerifyFailed(data);
      return shared_ptr<ValidationRequest>();
    }

  Name interestName = *interestPrefixName;
  interestName.append(nameList->at(0));

  if(forIntroducer)
    interestName.append("INTRODUCER");

  shared_ptr<ndn::Interest> interest = make_shared<ndn::Interest>(interestName);
  // _LOG_DEBUG("send interest for intro cert: " << interest->getName());

  OnVerified requestedCertVerifiedCallback = boost::bind(&SecPolicySync::onIntroCertVerified, 
                                                         this, 
                                                         _1,
                                                         forIntroducer, 
                                                         data,
                                                         onVerified,
                                                         onVerifyFailed);
                                                             
  OnVerifyFailed requestedCertUnverifiedCallback = boost::bind(&SecPolicySync::onIntroCertVerifyFailed, 
                                                               this, 
                                                               _1, 
                                                               interestPrefixName,
                                                               forIntroducer,
                                                               nameList,
                                                               1,
                                                               data,
                                                               onVerified,
                                                               onVerifyFailed);

    
  shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest, 
                                                                          requestedCertVerifiedCallback,
                                                                          requestedCertUnverifiedCallback,
                                                                          1,
                                                                          m_stepLimit-1);
  return nextStep;
}

void
SecPolicySync::OnIntroCertInterest(const shared_ptr<const Name>& prefix, 
                                       const shared_ptr<const ndn::Interest>& interest, 
                                       Transport& transport, 
                                       uint64_t registeredPrefixId)
{
  map<string, Data>::const_iterator it = m_introCert.find(prefix->toUri());

  if(m_introCert.end() != it)
    m_face->put(it->second);
}

void
SecPolicySync::OnIntroCertRegisterFailed(const shared_ptr<const Name>& prefix)
{
}

void
SecPolicySync::onIntroCertVerified(const shared_ptr<Data>& introCertificateData,
				       bool forIntroducer,
				       shared_ptr<Data> originalData,
				       const OnVerified& onVerified,
				       const OnVerifyFailed& onVerifyFailed)
{
  shared_ptr<SyncIntroCertificate> introCertificate = make_shared<SyncIntroCertificate>(*introCertificateData);
  if(forIntroducer)
    {
      m_trustedIntroducers.insert(pair <string, PublicKey > (introCertificate->getPublicKeyName().toUri(),
                                                             introCertificate->getPublicKeyInfo()));
      SyncIntroCertificate syncIntroCertificate(m_syncPrefix,
                                                introCertificate->getPublicKeyName(),
                                                m_keyChain->getDefaultKeyNameForIdentity(m_signingIdentity),
                                                introCertificate->getNotBefore(),
                                                introCertificate->getNotAfter(),
                                                introCertificate->getPublicKeyInfo(),
                                                SyncIntroCertificate::INTRODUCER);

      Name certName = m_keyChain->getDefaultCertificateNameForIdentity(m_signingIdentity);
      _LOG_DEBUG("Publish Intro Certificate on Verified: " << syncIntroCertificate.getName());
      m_keyChain->sign(syncIntroCertificate, certName);

      m_face->put(syncIntroCertificate);

      // Name prefix = syncIntroCertificate.getName().getPrefix(syncIntroCertificate.getName().size()-1);

      // map<string, Data>::const_iterator it = m_introCert.find(prefix.toEscapedString());
      // if(m_introCert.end() != it)
      //   {
      //     it->second = syncIntroCertificate;
      //   }
      // else
      //   {         
      //     m_introCert.insert(pair <string, Data> (prefix.toEscapedString(), syncIntroCertificate));
      //     m_face->registerPrefix(prefix, 
      //                           boost::bind(&SecPolicySync::onIntroCertInterest, this, _1, _2, _3, _4), 
      //                           boost::bind(&SecPolicySync::onIntroCertRegisterFailed, this, _1));
      //   }
    }
  else
    {
      m_trustedProducers.insert(pair <string, PublicKey > (introCertificate->getPublicKeyName().toUri(), 
                                                           introCertificate->getPublicKeyInfo()));
      SyncIntroCertificate syncIntroCertificate(m_syncPrefix,
                                                introCertificate->getPublicKeyName(),
                                                m_keyChain->getDefaultKeyNameForIdentity(m_signingIdentity),
                                                introCertificate->getNotBefore(),
                                                introCertificate->getNotAfter(),
                                                introCertificate->getPublicKeyInfo(),
                                                SyncIntroCertificate::PRODUCER);

      Name certName = m_keyChain->getDefaultCertificateNameForIdentity(m_signingIdentity);
      _LOG_DEBUG("Publish Intro Certificate on Verified: " << syncIntroCertificate.getName());
      m_keyChain->sign(syncIntroCertificate, certName);
      
      m_face->put(syncIntroCertificate);

      // Name prefix = syncIntroCertificate.getName().getPrefix(syncIntroCertificate.getName().size()-1);

      // map<string, Data>::const_iterator it = m_introCert.find(prefix.toEscapedString());
      // if(m_introCert.end() != it)
      //   {
      //     it->second = syncIntroCertificate;
      //   }
      // else
      //   {
      //     m_introCert.insert(pair <string, Data> (prefix.toEscapedString(), syncIntroCertificate));
      //     m_face->registerPrefix(prefix, 
      //                           boost::bind(&SecPolicySync::onIntroCertInterest, this, _1, _2, _3, _4), 
      //                           boost::bind(&SecPolicySync::onIntroCertRegisterFailed, this, _1));
      //   }
    }

  try{
    SignatureSha256WithRsa sig(originalData->getSignature());
    if(Verifier::verifySignature(*originalData, sig, introCertificate->getPublicKeyInfo()))      
      onVerified(originalData);    
    else
      onVerifyFailed(originalData);
  }catch(SignatureSha256WithRsa::Error &e){
    onVerifyFailed(originalData);
  }catch(KeyLocator::Error &e){
    onVerifyFailed(originalData);
  }
}

void 
SecPolicySync::onIntroCertVerifyFailed(const shared_ptr<Data>& introCertificateData,
                                           shared_ptr<Name> interestPrefixName,
                                           bool forIntroducer,
                                           shared_ptr<const vector<Name> > introNameList,
                                           int nextIntroducerIndex,
                                           shared_ptr<Data> originalData,
                                           const OnVerified& onVerified,
                                           const OnVerifyFailed& onVerifyFailed)
{
  Name interestName = *interestPrefixName;
  if(nextIntroducerIndex < introNameList->size())
    interestName.append(introNameList->at(nextIntroducerIndex));
  else
    onVerifyFailed(originalData);

  if(forIntroducer)
    interestName.append("INTRODUCER");
  
  shared_ptr<ndn::Interest> interest = make_shared<ndn::Interest>(interestName);

  OnVerified onRecursiveVerified = boost::bind(&SecPolicySync::onIntroCertVerified, 
                                      this, 
                                      _1,
                                      forIntroducer, 
                                      originalData,
                                      onVerified,
                                      onVerifyFailed);

  OnVerifyFailed onRecursiveVerifyFailed = boost::bind(&SecPolicySync::onIntroCertVerifyFailed, 
                                              this, 
                                              _1,
                                              interestPrefixName,
                                              forIntroducer,
                                              introNameList,
                                              nextIntroducerIndex + 1,
                                              originalData, 
                                              onVerified,
                                              onVerifyFailed);
        
  m_face->expressInterest(*interest, 
                          boost::bind(&SecPolicySync::onIntroCertData,
                                      this,
                                      _1,
                                      _2,     
                                      m_stepLimit-1,
                                      onRecursiveVerified,
                                      onRecursiveVerifyFailed,
                                      originalData,
                                      onVerifyFailed),
                          boost::bind(&SecPolicySync::onIntroCertTimeout, 
                                      this,
                                      _1,
                                      1,
                                      m_stepLimit-1,
                                      onRecursiveVerified,
                                      onRecursiveVerifyFailed,
                                      originalData,
                                      onVerifyFailed));
}

void
SecPolicySync::onIntroCertData(const shared_ptr<const ndn::Interest> &interest,
                                   const shared_ptr<Data>& introCertificateData,
                                   int stepCount,
                                   const OnVerified& onRecursiveVerified,
                                   const OnVerifyFailed& onRecursiveVerifyFailed,
                                   shared_ptr<Data> originalData,
                                   const OnVerifyFailed& onVerifyFailed)
{
  shared_ptr<ValidationRequest> nextStep = checkVerificationPolicy(introCertificateData, stepCount, onRecursiveVerified, onRecursiveVerifyFailed);
  if (nextStep)
    m_face->expressInterest
      (*nextStep->interest_, 
       boost::bind(&SecPolicySync::onIntroCertData, 
                   this, 
                   _1, 
                   _2,
                   nextStep->stepCount_,
                   nextStep->onVerified_, 
                   nextStep->onVerifyFailed_,
                   introCertificateData,
                   onRecursiveVerifyFailed), 
       boost::bind(&SecPolicySync::onIntroCertTimeout, 
                   this, 
                   _1, 
                   nextStep->retry_, 
                   nextStep->stepCount_, 
                   nextStep->onVerified_, 
                   nextStep->onVerifyFailed_,
                   introCertificateData,
                   onRecursiveVerifyFailed));
}

void
SecPolicySync::onIntroCertTimeout(const shared_ptr<const ndn::Interest>& interest, 
				      int retry, 
                                      int stepCount,
                                      const OnVerified& onRecursiveVerified,
                                      const OnVerifyFailed& onRecursiveVerifyFailed,
                                      shared_ptr<Data> originalData,
                                      const OnVerifyFailed& onVerifyFailed)
{
  if(retry > 0)
    {
      m_face->expressInterest(*interest, 
                              boost::bind(&SecPolicySync::onIntroCertData, 
                                          this,
                                          _1,
                                          _2,
                                          stepCount,
                                          onRecursiveVerified,
                                          onRecursiveVerifyFailed,
                                          originalData,
                                          onVerifyFailed),
                              boost::bind(&SecPolicySync::onIntroCertTimeout, 
                                          this,
                                          _1,
                                          retry - 1,
                                          stepCount,
                                          onRecursiveVerified,
                                          onRecursiveVerifyFailed,
                                          originalData,
                                          onVerifyFailed));
    }
  else
    onVerifyFailed(originalData);
}
