/* -*- 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 "invitation-policy-manager.h"

#include <ndn.cxx/security/certificate/identity-certificate.h>
#include <boost/bind.hpp>

#include "logging.h"

using namespace std;
using namespace ndn;
using namespace ndn::security;

INIT_LOGGER("InvitationPolicyManager");

InvitationPolicyManager::InvitationPolicyManager(const int & stepLimit,
						 Ptr<CertificateCache> certificateCache)
  : m_stepLimit(stepLimit)
  , m_certificateCache(certificateCache)
  , m_localPrefixRegex(Ptr<Regex>(new Regex("^<local><ndn><prefix><><>$")))
{
  m_invitationDataRule = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^<ndn><broadcast><chronos><invitation>([^<chatroom>]*)<chatroom>", 
									"^([^<KEY>]*)<KEY><DSK-.*><ID-CERT><>$", 
									"==", "\\1", "\\1", true));
  
  m_dskRule = Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><DSK-.*><ID-CERT><>$", 
							     "^([^<KEY>]*)<KEY>(<>*)<KSK-.*><ID-CERT><>$", 
							     "==", "\\1", "\\1\\2", true));

  m_keyNameRegex = Ptr<Regex>(new Regex("^([^<KEY>]*)<KEY>(<>*<KSK-.*>)<ID-CERT><>$", "\\1\\2"));

  m_signingCertificateRegex = Ptr<Regex>(new Regex("^<ndn><broadcast><chronos><invitation>([^<chatroom>]*)<chatroom>", "\\1"));
}

bool 
InvitationPolicyManager::skipVerifyAndTrust (const Data & data)
{
  if(m_localPrefixRegex->match(data.getName()))
    return true;
  
  return false;
}

bool
InvitationPolicyManager::requireVerify (const Data & data)
{
  if(m_invitationDataRule->matchDataName(data))
    return true;

  if(m_dskRule->matchDataName(data))
    return true;

  return false;
}

Ptr<ValidationRequest>
InvitationPolicyManager::checkVerificationPolicy(Ptr<Data> data, 
						 const int & stepCount, 
						 const DataCallback& verifiedCallback,
						 const UnverifiedCallback& unverifiedCallback)
{
  if(m_stepLimit == stepCount)
    {
      _LOG_DEBUG("reach the maximum steps of verification");
      unverifiedCallback(data);
      return NULL;
    }

  Ptr<const signature::Sha256WithRsa> sha256sig = boost::dynamic_pointer_cast<const signature::Sha256WithRsa> (data->getSignature());    

  if(KeyLocator::KEYNAME != sha256sig->getKeyLocator().getType())
    {
      unverifiedCallback(data);
      return NULL;
    }

  const Name & keyLocatorName = sha256sig->getKeyLocator().getKeyName();

  if(m_invitationDataRule->satisfy(*data))
    {
      Ptr<const IdentityCertificate> trustedCert = m_certificateCache->getCertificate(keyLocatorName);
      
      if(NULL != trustedCert){
	if(verifySignature(*data, trustedCert->getPublicKeyInfo()))
	  verifiedCallback(data);
	else
	  unverifiedCallback(data);

	return NULL;
      }
      else{
	_LOG_DEBUG("KeyLocator has not been cached and validated!");

	DataCallback recursiveVerifiedCallback = boost::bind(&InvitationPolicyManager::onCertificateVerified, 
							     this, 
							     _1, 
							     data, 
							     verifiedCallback, 
							     unverifiedCallback);

	UnverifiedCallback recursiveUnverifiedCallback = boost::bind(&InvitationPolicyManager::onCertificateUnverified, 
								     this, 
								     _1, 
								     data, 
								     unverifiedCallback);


	Ptr<Interest> interest = Ptr<Interest>(new Interest(sha256sig->getKeyLocator().getKeyName()));
	
	Ptr<ValidationRequest> nextStep = Ptr<ValidationRequest>(new ValidationRequest(interest, 
										       recursiveVerifiedCallback,
										       recursiveUnverifiedCallback,
										       0,
										       stepCount + 1)
								 );
	return nextStep;
      }
    }

  if(m_dskRule->satisfy(*data))
    {
      m_keyNameRegex->match(keyLocatorName);
      Name keyName = m_keyNameRegex->expand();

      if(m_trustAnchors.end() != m_trustAnchors.find(keyName))
        if(verifySignature(*data, m_trustAnchors[keyName]))
          verifiedCallback(data);
        else
          unverifiedCallback(data);
      else
        unverifiedCallback(data);

      return NULL;	
    }

  unverifiedCallback(data);
  return NULL;
}

void 
InvitationPolicyManager::onCertificateVerified(Ptr<Data> certData, 
					       Ptr<Data> originalData,
					       const DataCallback& verifiedCallback, 
					       const UnverifiedCallback& unverifiedCallback)
{
  IdentityCertificate certificate(*certData);

  if(verifySignature(*originalData, certificate.getPublicKeyInfo()))
    verifiedCallback(originalData);
  else
    unverifiedCallback(originalData);
}

void
InvitationPolicyManager::onCertificateUnverified(Ptr<Data> certData, 
						 Ptr<Data> originalData,
						 const UnverifiedCallback& unverifiedCallback)
{ unverifiedCallback(originalData); }

bool 
InvitationPolicyManager::checkSigningPolicy(const Name & dataName, const Name & certificateName)
{
  return m_invitationDataRule->satisfy(dataName, certificateName);
}

Name 
InvitationPolicyManager::inferSigningIdentity(const Name & dataName)
{
  if(m_signingCertificateRegex->match(dataName))
    return m_signingCertificateRegex->expand();
  else
    return Name();
}

void
InvitationPolicyManager::addTrustAnchor(const EndorseCertificate& selfEndorseCertificate)
{ m_trustAnchors.insert(pair <Name, Publickey > (selfEndorseCertificate.getPublicKeyName(), selfEndorseCertificate.getPublicKeyInfo())); }
