/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "common.hpp"

#include "validator-regex.hpp"
#include "signature-sha256-with-rsa.hpp"
#include "certificate-cache-ttl.hpp"

#include "../util/logging.hpp"

INIT_LOGGER("ndn::ValidatorRegex");

using namespace std;

namespace ndn
{

const shared_ptr<CertificateCache> ValidatorRegex::DefaultCertificateCache = shared_ptr<CertificateCache>();

ValidatorRegex::ValidatorRegex(shared_ptr<Face> face,
                               shared_ptr<CertificateCache> certificateCache /* = DefaultCertificateCache */,
                               const int stepLimit /* = 3 */)
  : Validator(face)
  , m_stepLimit(stepLimit)
  , m_certificateCache(certificateCache)
{
  if(!static_cast<bool>(face))
    throw Error("Face is not set!");

  if(!static_cast<bool>(m_certificateCache))
    m_certificateCache = make_shared<CertificateCacheTtl>(m_face->ioService());
}

void
ValidatorRegex::onCertificateValidated(const shared_ptr<const Data> &signCertificate, 
                                       const shared_ptr<const Data> &data, 
                                       const OnDataValidated &onValidated, 
                                       const OnDataValidationFailed &onValidationFailed)
{
  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*signCertificate);
  
  if(!certificate->isTooLate() && !certificate->isTooEarly())
    {
      m_certificateCache->insertCertificate(certificate);
      
      try{
        if(verifySignature(*data, certificate->getPublicKeyInfo()))
          {
            onValidated(data);
            return;
          }
      }catch(Signature::Error &e){
        _LOG_DEBUG("ValidatorRegex Error: " << e.what());
        onValidationFailed(data);
        return;
      }
    }
  else
    {
      _LOG_DEBUG("Wrong Invalidity:");
      onValidationFailed(data);
      return;
    }
}

void
ValidatorRegex::onCertificateValidationFailed(const shared_ptr<const Data> &signCertificate, 
                                              const shared_ptr<const Data> &data, 
                                              const OnDataValidationFailed &onValidationFailed)
{ onValidationFailed(data); }

void
ValidatorRegex::checkPolicy(const Data& data, 
                            int stepCount, 
                            const OnDataValidated &onValidated, 
                            const OnDataValidationFailed &onValidationFailed,
                            vector<shared_ptr<ValidationRequest> > &nextSteps)
{
  if(m_stepLimit == stepCount){
    _LOG_DEBUG("reach the maximum steps of verification");
    onValidationFailed(data.shared_from_this());
    return;
  }
  
  RuleList::iterator it = m_mustFailVerify.begin();
  for(; it != m_mustFailVerify.end(); it++)
    if((*it)->satisfy(data))
      {
        onValidationFailed(data.shared_from_this());
        return;
      }

  it = m_verifyPolicies.begin();
  for(; it != m_verifyPolicies.end(); it++)
    {
      if((*it)->satisfy(data))
        {
          try{
            SignatureSha256WithRsa sig(data.getSignature());                
            
            Name keyLocatorName = sig.getKeyLocator().getName();
            shared_ptr<const Certificate> trustedCert;
            if(m_trustAnchors.end() == m_trustAnchors.find(keyLocatorName))
              trustedCert = m_certificateCache->getCertificate(keyLocatorName);
            else
              trustedCert = m_trustAnchors[keyLocatorName];
            
            if(static_cast<bool>(trustedCert)){
              if(verifySignature(data, sig, trustedCert->getPublicKeyInfo()))
                onValidated(data.shared_from_this());
              else
                onValidationFailed(data.shared_from_this());
              
              return;
            }
            else{
              // _LOG_DEBUG("KeyLocator is not trust anchor");                
              OnDataValidated onKeyValidated = bind(&ValidatorRegex::onCertificateValidated, this, 
                                                    _1, data.shared_from_this(), onValidated, onValidationFailed);
              
              OnDataValidationFailed onKeyValidationFailed = bind(&ValidatorRegex::onCertificateValidationFailed, this, 
                                                                  _1, data.shared_from_this(), onValidationFailed);              

              shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(Interest(boost::cref(sig.getKeyLocator().getName())), 
                                                                                      onKeyValidated,
                                                                                      onKeyValidationFailed,
                                                                                      3,
                                                                                      stepCount + 1);
              nextSteps.push_back(nextStep);
              return;
            }
          }catch(SignatureSha256WithRsa::Error &e){
            _LOG_DEBUG("ValidatorRegex Error: " << e.what());
            onValidationFailed(data.shared_from_this());
            return;
          }catch(KeyLocator::Error &e){
            _LOG_DEBUG("ValidatorRegex Error: " << e.what());
            onValidationFailed(data.shared_from_this());
            return;
          }
        }
    }

  onValidationFailed(data.shared_from_this());
  return;
}

}//ndn
