/* -*- 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>
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "common.hpp"

#include "security/certificate.hpp"

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

#include <cryptopp/asn.h>
#include <cryptopp/base64.h>
#include <cryptopp/files.h>

#include "../encoding/cryptopp/asn_ext.hpp"

INIT_LOGGER("ndn.security.Certificate");

using namespace std;

namespace ndn {

Certificate::Certificate()
  : notBefore_(std::numeric_limits<MillisecondsSince1970>::max())
  , notAfter_(std::numeric_limits<MillisecondsSince1970>::min())
{}

Certificate::Certificate(const Data& data)
// Use the copy constructor.  It clones the signature object.
: Data(data)
{
  // _LOG_DEBUG("Finish local copy: " << getContent().getContent().size());

  decode();
}

Certificate::~Certificate()
{
  //TODO:
}

bool
Certificate::isTooEarly()
{
  MillisecondsSince1970 now = ndn_getNowMilliseconds();
  if(now < notBefore_)
    return true;
  else
    return false;
}

bool 
Certificate::isTooLate()
{
  MillisecondsSince1970 now = ndn_getNowMilliseconds();
  if(now > notAfter_)
    return true;
  else
    return false;
}

void
Certificate::encode()
{
  // Name
  //    <key_name>/ID-CERT/<id#>
  // Content
  // DER encoded idCert:
  //
  // 	idCert ::= SEQUENCE {
  //        validity            Validity,
  // 	    subject             Name,
  // 	    subjectPubKeyInfo   SubjectPublicKeyInfo,
  // 	    extension           Extensions OPTIONAL   }
  //
  // 	Validity ::= SEQUENCE {
  //        notBefore           Time,
  //        notAfter            Time   }
  //
  //    Name ::= CHOICE {
  //        RDNSequence   }
  //
  //    RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
  //
  //    RelativeDistinguishedName ::=
  //        SET OF AttributeTypeAndValue
  //
  // 	SubjectPublicKeyInfo ::= SEQUENCE {
  //        algorithm           AlgorithmIdentifier
  //        keybits             BIT STRING   }
  //
  //    Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
  //
  // (see http://www.ietf.org/rfc/rfc3280.txt for more detail)
  //
  // KeyLocator
  //    issuer’s certificate name
  // Signature

  using namespace CryptoPP;

  OBufferStream os;
  CryptoPP::FileSink sink(os);
  
  // idCert ::= SEQUENCE {
  //     validity            Validity,
  //     subject             Name,
  //     subjectPubKeyInfo   SubjectPublicKeyInfo,
  //     extension           Extensions OPTIONAL   }
  DERSequenceEncoder idCert(sink);
  {
    // Validity ::= SEQUENCE {
    //       notBefore           Time,
    //       notAfter            Time   }
    DERSequenceEncoder validity(idCert);
    {
      DEREncodeGeneralTime(validity, notBefore_);
      DEREncodeGeneralTime(validity, notAfter_);
    }
    validity.MessageEnd();

    // Name ::= CHOICE {
    //     RDNSequence   }
    // 
    // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
    DERSequenceEncoder name(idCert);
    {
      for(SubjectDescriptionList::iterator it = subjectDescriptionList_.begin();
          it != subjectDescriptionList_.end(); ++it)
        {
          it->encode(name);
        }
    }
    name.MessageEnd();
  
    // SubjectPublicKeyInfo
    key_.encode(idCert);

    // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
    //
    // Extension ::= SEQUENCE {
    //        extnID      OBJECT IDENTIFIER,
    //        critical    BOOLEAN DEFAULT FALSE,
    //        extnValue   OCTET STRING  }
    if(!extensionList_.empty())
      {
        DERSequenceEncoder extensions(idCert);
        {
          
          for(ExtensionList::iterator it = extensionList_.begin();
              it != extensionList_.end(); ++it)
            {
              it->encode(extensions);
            }
        }
        extensions.MessageEnd();
      }
  }

  idCert.MessageEnd();

  setContent(os.buf());
  setContentType(MetaInfo::TYPE_KEY);
}

void 
Certificate::decode()
{
  using namespace CryptoPP;

  OBufferStream os;
  CryptoPP::StringSource source(getContent().value(), getContent().value_size(), true);
  
  // idCert ::= SEQUENCE {
  //     validity            Validity,
  //     subject             Name,
  //     subjectPubKeyInfo   SubjectPublicKeyInfo,
  //     extension           Extensions OPTIONAL   }
  BERSequenceDecoder idCert(source);
  {
    // Validity ::= SEQUENCE {
    //       notBefore           Time,
    //       notAfter            Time   }
    BERSequenceDecoder validity(idCert);
    {
      BERDecodeTime(validity, notBefore_);
      BERDecodeTime(validity, notAfter_);
    }
    validity.MessageEnd();

    // Name ::= CHOICE {
    //     RDNSequence   }
    // 
    // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
    subjectDescriptionList_.clear();
    BERSequenceDecoder name(idCert);
    {
      while(!name.EndReached())
        {
          subjectDescriptionList_.push_back(CertificateSubjectDescription(name));
        }
    }
    name.MessageEnd();
  
    // SubjectPublicKeyInfo ::= SEQUENCE {
    //     algorithm           AlgorithmIdentifier
    //     keybits             BIT STRING   }
    key_.decode(idCert);

    // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
    //
    // Extension ::= SEQUENCE {
    //        extnID      OBJECT IDENTIFIER,
    //        critical    BOOLEAN DEFAULT FALSE,
    //        extnValue   OCTET STRING  }
    extensionList_.clear();
    if(!idCert.EndReached())
      {
        BERSequenceDecoder extensions(idCert);
        {
          while(!extensions.EndReached())
            {
              extensionList_.push_back(CertificateExtension(extensions));
            }
        }
        extensions.MessageEnd();
      }
  }

  idCert.MessageEnd();
}

void 
Certificate::printCertificate(std::ostream &os) const
{
  os << "Certificate name:" << endl;
  os << "  " << getName() << endl;
  os << "Validity:" << endl;
  {
    os << "  NotBefore: " << toIsoString(notBefore_) << endl;
    os << "  NotAfter: "  << toIsoString(notAfter_)  << endl;
  }

  os << "Subject Description:" << endl;  
  for(SubjectDescriptionList::const_iterator it = subjectDescriptionList_.begin();
      it != subjectDescriptionList_.end(); ++it)
    {
      os << "  " << it->getOidString() << ": " << it->getValue() << endl;
    }

  os << "Public key bits:" << endl;
  CryptoPP::Base64Encoder encoder(new CryptoPP::FileSink(os), true, 64);
  key_.encode(encoder);
  
  // ndnboost::iostreams::stream<ndnboost::iostreams::array_source> is((const char*)key_.getKeyDer().buf(), key_.getKeyDer().size());

  // ptr_lib::shared_ptr<der::DerNode> keyRoot = der::DerNode::parse(reinterpret_cast<der::InputIterator&> (is));

  // der::PrintVisitor printVisitor;
  // keyRoot->accept(printVisitor, string(""));
}

}
