/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2014 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 * @author Jeff Thompson <jefft0@remap.ucla.edu>
 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
 */

#ifndef NDN_SECURITY_CERTIFICATE_HPP
#define NDN_SECURITY_CERTIFICATE_HPP

#include "../common.hpp"
#include "../data.hpp"
#include "certificate-subject-description.hpp"
#include "certificate-extension.hpp"
#include "public-key.hpp"

namespace ndn {

class Certificate : public Data
{
public:
  class Error : public std::runtime_error
  {
  public:
    explicit
    Error(const std::string& what)
      : std::runtime_error(what)
    {
    }
  };

  typedef std::vector<CertificateSubjectDescription> SubjectDescriptionList;
  typedef std::vector<CertificateExtension> ExtensionList;

  /**
   * The default constructor.
   */
  Certificate();

  /**
   * Create a Certificate from the content in the data packet.
   * @param data The data packet with the content to decode.
   */
  Certificate(const Data& data);

  /**
   * The virtual destructor.
   */
  virtual
  ~Certificate();

  inline void
  wireDecode(const Block& wire);

  /**
   * encode certificate info into content
   */
  void
  encode();

  /**
   * Add a subject description.
   * @param description The description to be added.
   */
  void
  addSubjectDescription(const CertificateSubjectDescription& description)
  {
    m_subjectDescriptionList.push_back(description);
  }

  const SubjectDescriptionList&
  getSubjectDescriptionList() const
  {
    return m_subjectDescriptionList;
  }

  SubjectDescriptionList&
  getSubjectDescriptionList()
  {
    return m_subjectDescriptionList;
  }

  /**
   * Add a certificate extension.
   * @param extension the extension to be added
   */
  void
  addExtension(const CertificateExtension& extension)
  {
    m_extensionList.push_back(extension);
  }

  const ExtensionList&
  getExtensionList() const
  {
    return m_extensionList;
  }

  ExtensionList&
  getExtensionList()
  {
    return m_extensionList;
  }

  void
  setNotBefore(const time::system_clock::TimePoint& notBefore)
  {
    m_notBefore = notBefore;
  }

  time::system_clock::TimePoint&
  getNotBefore()
  {
    return m_notBefore;
  }

  const time::system_clock::TimePoint&
  getNotBefore() const
  {
    return m_notBefore;
  }

  void
  setNotAfter(const time::system_clock::TimePoint& notAfter)
  {
    m_notAfter = notAfter;
  }

  time::system_clock::TimePoint&
  getNotAfter()
  {
    return m_notAfter;
  }

  const time::system_clock::TimePoint&
  getNotAfter() const
  {
    return m_notAfter;
  }

  void
  setPublicKeyInfo(const PublicKey& key)
  {
    m_key = key;
  }

  PublicKey&
  getPublicKeyInfo()
  {
    return m_key;
  }

  const PublicKey&
  getPublicKeyInfo() const
  {
    return m_key;
  }

  /**
   * Check if the certificate is valid.
   * @return True if the current time is earlier than notBefore.
   */
  bool
  isTooEarly();

  /**
   * Check if the certificate is valid.
   * @return True if the current time is later than notAfter.
   */
  bool
  isTooLate();

  void
  printCertificate(std::ostream& os) const;

protected:
  void
  decode();

protected:
  SubjectDescriptionList m_subjectDescriptionList;
  time::system_clock::TimePoint m_notBefore;
  time::system_clock::TimePoint m_notAfter;
  PublicKey m_key;
  ExtensionList m_extensionList;
};

inline void
Certificate::wireDecode(const Block& wire)
{
  Data::wireDecode(wire);
  decode();
}


inline std::ostream&
operator<<(std::ostream& os, const Certificate& cert)
{
  cert.printCertificate(os);
  return os;
}

} // namespace ndn

#endif //NDN_SECURITY_CERTIFICATE_HPP
