/* -*- 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 <ndn-cpp/common.hpp>

#include "certificate.hpp"

#if NDN_CPP_USE_SYSTEM_BOOST
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/array.hpp>
namespace ndnboost = boost;
#else
// We can use ndnboost::iostreams because this is internal and will not conflict with the application if it uses boost::iostreams.
#include <ndnboost/iostreams/stream.hpp>
#include <ndnboost/iostreams/device/array.hpp>
#endif

#include "../../util/logging.hpp"
// #include "../../util/blob-stream.hpp"
// #include <ndn-cpp/security/certificate/certificate.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(""));
}

}
