/* -*- 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/>
 */

#ifndef NDN_SECURITY_CONF_CHECKER_HPP
#define NDN_SECURITY_CONF_CHECKER_HPP

#include "common.hpp"

#include "key-locator-checker.hpp"
#include "../../util/io.hpp"
#include "../validator.hpp"

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>

namespace ndn {
namespace security {
namespace conf {

class Checker
{
public:
  typedef function<void(const shared_ptr<const Interest>&)> OnInterestChecked;
  typedef function<void(const shared_ptr<const Interest>&,
                        const std::string&)> OnInterestCheckFailed;
  typedef function<void(const shared_ptr<const Data>&)> OnDataChecked;
  typedef function<void(const shared_ptr<const Data>&, const std::string&)> OnDataCheckFailed;

  enum {
    INTEREST_SIG_VALUE = -1,
    INTEREST_SIG_INFO = -2
  };


  virtual
  ~Checker()
  {
  }

  /**
   * @brief check if data satisfies condition defined in the specific checker implementation
   *
   * @param data Data packet
   * @param onValidated Callback function which is called when data is immediately valid
   * @param onValidationFailed Call function which is called when data is immediately invalid
   * @return -1 if data is immediately invalid (onValidationFailed has been called)
   *          1 if data is immediately valid (onValidated has been called)
   *          0 if further signature verification is needed.
   */
  virtual int8_t
  check(const Data& data,
        const OnDataChecked& onValidated,
        const OnDataCheckFailed& onValidationFailed) = 0;

  /**
   * @brief check if interest satisfies condition defined in the specific checker implementation
   *
   * @param interest Interest packet
   * @param onValidated Callback function which is called when interest is immediately valid
   * @param onValidationFailed Call function which is called when interest is immediately invalid
   * @return -1 if interest is immediately invalid (onValidationFailed has been called)
   *          1 if interest is immediately valid (onValidated has been called)
   *          0 if further signature verification is needed.
   */
  virtual int8_t
  check(const Interest& interest,
        const OnInterestChecked& onValidated,
        const OnInterestCheckFailed& onValidationFailed) = 0;
};

class CustomizedChecker : public Checker
{
public:
  CustomizedChecker(uint32_t sigType,
                    shared_ptr<KeyLocatorChecker> keyLocatorChecker)
    : m_sigType(sigType)
    , m_keyLocatorChecker(keyLocatorChecker)
  {
    switch (sigType)
      {
      case Tlv::SignatureSha256WithRsa:
      case Tlv::SignatureSha256WithEcdsa:
        {
          if (!static_cast<bool>(m_keyLocatorChecker))
            throw Error("Strong signature requires KeyLocatorChecker");

          return;
        }
      case Tlv::DigestSha256:
        return;
      default:
        throw Error("Unsupported signature type");
      }
  }

  virtual int8_t
  check(const Data& data,
        const OnDataChecked& onValidated,
        const OnDataCheckFailed& onValidationFailed)
  {
    return check(data, data.getSignature(), onValidated, onValidationFailed);
  }

  virtual int8_t
  check(const Interest& interest,
        const OnInterestChecked& onValidated,
        const OnInterestCheckFailed& onValidationFailed)
  {
    try
      {
        const Name& interestName = interest.getName();
        Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
                            interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
        return check(interest, signature, onValidated, onValidationFailed);
      }
    catch (Signature::Error& e)
      {
        onValidationFailed(interest.shared_from_this(), "Invalid signature");
        return -1;
      }
    catch (Tlv::Error& e)
      {
        onValidationFailed(interest.shared_from_this(), "Cannot decode signature related TLVs");
        return -1;
      }
  }

private:
  template<class Packet, class OnValidated, class OnFailed>
  int8_t
  check(const Packet& packet, const Signature& signature,
        const OnValidated& onValidated,
        const OnFailed& onValidationFailed)
  {
    if (m_sigType != signature.getType())
      {
        onValidationFailed(packet.shared_from_this(),
                           "Signature type does not match: " +
                           boost::lexical_cast<std::string>(m_sigType) +
                           "!=" +
                           boost::lexical_cast<std::string>(signature.getType()));
        return -1;
      }

    if (signature.getType() == Tlv::DigestSha256)
      return 0;

    shared_ptr<SignatureWithPublicKey> publicKeySig;

    try
      {
        switch (signature.getType())
          {
          case Tlv::SignatureSha256WithRsa:
            {
              publicKeySig = make_shared<SignatureSha256WithRsa>(signature);
              break;
            }
          case Tlv::SignatureSha256WithEcdsa:
            {
              publicKeySig = make_shared<SignatureSha256WithEcdsa>(signature);
              break;
            }
          default:
            {
              onValidationFailed(packet.shared_from_this(),
                                 "Unsupported signature type: " +
                                 boost::lexical_cast<std::string>(signature.getType()));
              return -1;
            }
          }
      }
    catch (Tlv::Error& e)
      {
        onValidationFailed(packet.shared_from_this(),
                           "Cannot decode signature");
        return -1;
      }
    catch (KeyLocator::Error& e)
      {
        onValidationFailed(packet.shared_from_this(),
                           "Cannot decode KeyLocator");
        return -1;
      }

    std::string failInfo;
    if (m_keyLocatorChecker->check(packet, publicKeySig->getKeyLocator(), failInfo))
      return 0;
    else
      {
        onValidationFailed(packet.shared_from_this(), failInfo);
        return -1;
      }
  }

private:
  uint32_t m_sigType;
  shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
};

class HierarchicalChecker : public CustomizedChecker
{
public:
  explicit
  HierarchicalChecker(uint32_t sigType)
    : CustomizedChecker(sigType,
        make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
                                                "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
                                                "\\1\\2",
                                                KeyLocatorChecker::RELATION_IS_PREFIX_OF))
  {
  }
};

class FixedSignerChecker : public Checker
{
public:
  FixedSignerChecker(uint32_t sigType,
                     const std::vector<shared_ptr<IdentityCertificate> >& signers)
    : m_sigType(sigType)
  {
    for (std::vector<shared_ptr<IdentityCertificate> >::const_iterator it = signers.begin();
         it != signers.end(); it++)
      m_signers[(*it)->getName().getPrefix(-1)] = (*it);

    if (sigType != Tlv::SignatureSha256WithRsa &&
        sigType != Tlv::SignatureSha256WithEcdsa)
      {
        throw Error("FixedSigner is only meaningful for strong signature type");
      }

  }

  virtual int8_t
  check(const Data& data,
        const OnDataChecked& onValidated,
        const OnDataCheckFailed& onValidationFailed)
  {
    return check(data, data.getSignature(), onValidated, onValidationFailed);
  }

  virtual int8_t
  check(const Interest& interest,
        const OnInterestChecked& onValidated,
        const OnInterestCheckFailed& onValidationFailed)
  {
    try
      {
        const Name& interestName = interest.getName();
        Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
                            interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
        return check(interest, signature, onValidated, onValidationFailed);
      }
    catch (Signature::Error& e)
      {
        onValidationFailed(interest.shared_from_this(), "Invalid signature");
        return -1;
      }
    catch (Tlv::Error& e)
      {
        onValidationFailed(interest.shared_from_this(), "Cannot decode signature related TLVs");
        return -1;
      }
  }

private:
  template<class Packet, class OnValidated, class OnFailed>
  int8_t
  check(const Packet& packet, const Signature& signature,
        const OnValidated& onValidated,
        const OnFailed& onValidationFailed)
  {
    if (m_sigType != signature.getType())
      {
        onValidationFailed(packet.shared_from_this(),
                           "Signature type does not match: " +
                           boost::lexical_cast<std::string>(m_sigType) +
                           "!=" +
                           boost::lexical_cast<std::string>(signature.getType()));
        return -1;
      }

    if (signature.getType() == Tlv::DigestSha256)
      {
        onValidationFailed(packet.shared_from_this(),
                           "FixedSigner does not allow Sha256 signature type");
        return -1;
      }

    shared_ptr<SignatureWithPublicKey> publicKeySig;

    try
      {
        switch (signature.getType())
          {
          case Tlv::SignatureSha256WithRsa:
            {
              publicKeySig = make_shared<SignatureSha256WithRsa>(signature);
              break;
            }
          case Tlv::SignatureSha256WithEcdsa:
            {
              publicKeySig = make_shared<SignatureSha256WithEcdsa>(signature);
              break;
            }
          default:
            {
              onValidationFailed(packet.shared_from_this(),
                                 "Unsupported signature type: " +
                                 boost::lexical_cast<std::string>(signature.getType()));
              return -1;
            }
          }

        const Name& keyLocatorName = publicKeySig->getKeyLocator().getName();

        if (m_signers.find(keyLocatorName) == m_signers.end())
          {
            onValidationFailed(packet.shared_from_this(),
                               "Signer is not in the fixed signer list: " +
                               keyLocatorName.toUri());
            return -1;
          }

        if (Validator::verifySignature(packet, *publicKeySig,
                                       m_signers[keyLocatorName]->getPublicKeyInfo()))
          {
            onValidated(packet.shared_from_this());
            return 1;
          }
        else
          {
            onValidationFailed(packet.shared_from_this(),
                               "Signature cannot be validated");
            return -1;
          }
      }
    catch (KeyLocator::Error& e)
      {
        onValidationFailed(packet.shared_from_this(),
                           "KeyLocator does not have name");
        return -1;
      }
    catch (Tlv::Error& e)
      {
        onValidationFailed(packet.shared_from_this(),
                           "Cannot decode signature");
        return -1;
      }
  }

private:
  typedef std::map<Name, shared_ptr<IdentityCertificate> > SignerList;

  uint32_t m_sigType;
  SignerList m_signers;
};

class CheckerFactory
{
public:
  /**
   * @brief create a checker from configuration file.
   *
   * @param configSection The section containing the definition of checker.
   * @param configFilename The configuration file name.
   * @return a shared pointer to the created checker.
   */
  static shared_ptr<Checker>
  create(const ConfigSection& configSection, const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();

    // Get checker.type
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
      throw Error("Expect <checker.type>");

    std::string type = propertyIt->second.data();

    if (boost::iequals(type, "customized"))
      return createCustomizedChecker(configSection, configFilename);
    else if (boost::iequals(type, "hierarchical"))
      return createHierarchicalChecker(configSection, configFilename);
    else if (boost::iequals(type, "fixed-signer"))
      return createFixedSignerChecker(configSection, configFilename);
    else
      throw Error("Unsupported checker type: " + type);
  }

private:
  static shared_ptr<Checker>
  createCustomizedChecker(const ConfigSection& configSection,
                          const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();
    propertyIt++;

    // Get checker.sig-type
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
      throw Error("Expect <checker.sig-type>");

    std::string sigType = propertyIt->second.data();
    propertyIt++;

    // Get checker.key-locator
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
      throw Error("Expect <checker.key-locator>");

    shared_ptr<KeyLocatorChecker> keyLocatorChecker =
      KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
    propertyIt++;

    if (propertyIt != configSection.end())
      throw Error("Expect the end of checker");

    return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
  }

  static shared_ptr<Checker>
  createHierarchicalChecker(const ConfigSection& configSection,
                            const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();
    propertyIt++;

    // Get checker.sig-type
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
      throw Error("Expect <checker.sig-type>");

    std::string sigType = propertyIt->second.data();
    propertyIt++;

    if (propertyIt != configSection.end())
      throw Error("Expect the end of checker");

    return make_shared<HierarchicalChecker>(getSigType(sigType));
  }

  static shared_ptr<Checker>
  createFixedSignerChecker(const ConfigSection& configSection,
                           const std::string& configFilename)
  {
    ConfigSection::const_iterator propertyIt = configSection.begin();
    propertyIt++;

    // Get checker.sig-type
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
      throw Error("Expect <checker.sig-type>");

    std::string sigType = propertyIt->second.data();
    propertyIt++;

    std::vector<shared_ptr<IdentityCertificate> > signers;
    for (; propertyIt != configSection.end(); propertyIt++)
      {
        if (!boost::iequals(propertyIt->first, "signer"))
          throw Error("Expect <checker.signer> but get <checker." +
                      propertyIt->first + ">");

        signers.push_back(getSigner(propertyIt->second, configFilename));
      }

    if (propertyIt != configSection.end())
      throw Error("Expect the end of checker");

    return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
                                                                 signers));
  }

  static shared_ptr<IdentityCertificate>
  getSigner(const ConfigSection& configSection, const std::string& configFilename)
  {
    using namespace boost::filesystem;

    ConfigSection::const_iterator propertyIt = configSection.begin();

    // Get checker.signer.type
    if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
      throw Error("Expect <checker.signer.type>");

    std::string type = propertyIt->second.data();
    propertyIt++;

    if (boost::iequals(type, "file"))
      {
        // Get checker.signer.file-name
        if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
          throw Error("Expect <checker.signer.file-name>");

        path certfilePath = absolute(propertyIt->second.data(),
                                     path(configFilename).parent_path());
        propertyIt++;

        if (propertyIt != configSection.end())
          throw Error("Expect the end of checker.signer");

        shared_ptr<IdentityCertificate> idCert
          = io::load<IdentityCertificate>(certfilePath.c_str());

        if (static_cast<bool>(idCert))
          return idCert;
        else
          throw Error("Cannot read certificate from file: " +
                      certfilePath.native());
      }
    else if (boost::iequals(type, "base64"))
      {
        // Get checker.signer.base64-string
        if (propertyIt == configSection.end() ||
            !boost::iequals(propertyIt->first, "base64-string"))
          throw Error("Expect <checker.signer.base64-string>");

        std::stringstream ss(propertyIt->second.data());
        propertyIt++;

        if (propertyIt != configSection.end())
          throw Error("Expect the end of checker.signer");

        shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);

        if (static_cast<bool>(idCert))
          return idCert;
        else
          throw Error("Cannot decode certificate from string");
      }
    else
      throw Error("Unsupported checker.signer type: " + type);
  }

  static uint32_t
  getSigType(const std::string& sigType)
  {
    if (boost::iequals(sigType, "rsa-sha256"))
      return Tlv::SignatureSha256WithRsa;
    else if (boost::iequals(sigType, "ecdsa-sha256"))
      return Tlv::SignatureSha256WithEcdsa;
    else if (boost::iequals(sigType, "sha256"))
      return Tlv::DigestSha256;
    else
      throw Error("Unsupported signature type");
  }
};

} // namespace conf
} // namespace security
} // namespace ndn

#endif // NDN_SECURITY_CONF_CHECKER_HPP
