// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef TINK_CORE_KEY_TYPE_MANAGER_H_
#define TINK_CORE_KEY_TYPE_MANAGER_H_

#include <tuple>

#include "absl/strings/str_cat.h"
#include "tink/core/template_util.h"
#include "tink/input_stream.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {

namespace internal {
// InternalKeyFactory should not be used directly: it is an implementation
// detail. The internal key factory provides the functions which are required
// if a KeyTypeManager can create new keys: ValidateKeyFormat and
// CreateKey. The special case where KeyFormatProto = void implies that the
// functions do not exist.
template <typename KeyProto, typename KeyFormatProto>
class InternalKeyFactory {
 public:
  virtual ~InternalKeyFactory() {}

  // Validates a key format proto.  KeyFormatProtos
  // on which this function returns a non-ok status will not be passed to
  // CreateKey or DeriveKey.
  virtual crypto::tink::util::Status ValidateKeyFormat(
      const KeyFormatProto& key_format) const = 0;
  // Creates a new key. This is expected to be randomized.
  virtual crypto::tink::util::StatusOr<KeyProto> CreateKey(
      const KeyFormatProto& key_format) const = 0;
  // Creates a new key. Only needs to be overridden if it should be possible to
  // derive keys of this type. This must be deterministic. Furthermore, in order
  // to support long term usability of old keys, the KeyFormatProto should be
  // versioned.
  virtual crypto::tink::util::StatusOr<KeyProto> DeriveKey(
      const KeyFormatProto& key_format, InputStream* input_stream) const {
    return crypto::tink::util::Status(
        crypto::tink::util::error::UNIMPLEMENTED,
        "Deriving key not implemented for this key type.");
  }
};

// Template specialization for when KeyFormatProto = void. The compiler will
// pick the most specialized template when compiling.
template <typename KeyProto>
class InternalKeyFactory<KeyProto, void> {
 public:
  virtual ~InternalKeyFactory() {}
};

}  // namespace internal

// We declare a KeyTypeManager without giving an implementation. We then
// provide a specialization only for the case where PrimitivesList is a
// List with multiple interfaces primitives. This allows to ensure
// that such is always the case.
template <typename KeyProto, typename KeyFormatProto, typename PrimitivesList>
class KeyTypeManager;

// A KeyTypeManager manages a single key proto. This includes
//  * parsing and validating keys
//  * parsing and validating key formats (in case generating keys is allowed).
//  * creating primitives.
// To implement, one should subclass KeyTypeManager with the corresponding
// KeyProto as a template parameter; KeyFormatProto should be void in case
// the key manager cannot produce keys and a protobuf otherwise.
//
// The constructor should take unique pointers to primitive factories.
//
// KeyTypeManager uses templates for KeyProto, KeyFormatProto and a list of
// Primitives which have to be provided as a List.
template <typename KeyProtoParam, typename KeyFormatProtoParam,
          typename... Primitives>
class KeyTypeManager<KeyProtoParam, KeyFormatProtoParam, List<Primitives...>>
    : public internal::InternalKeyFactory<KeyProtoParam, KeyFormatProtoParam> {
 public:
  static_assert(
      !crypto::tink::internal::HasDuplicates<Primitives...>::value,
      "List or primitives contains a duplicate, which is not allowed.");
  // The types used in this key type manager; these can be useful when writing
  // templated code.
  using KeyProto = KeyProtoParam;
  using KeyFormatProto = KeyFormatProtoParam;
  using PrimitiveList = List<Primitives...>;

  // A PrimitiveFactory<Primitive> knows how to create instances of the
  // Primitive.
  template <typename Primitive>
  class PrimitiveFactory {
   public:
    virtual ~PrimitiveFactory() {}
    virtual crypto::tink::util::StatusOr<std::unique_ptr<Primitive>> Create(
        const KeyProto& key) const = 0;
  };

  // Creates a new KeyTypeManager. The parameter(s) primitives must be some
  // number of unique_ptr<PrimitiveFactory<P>> types.
  explicit KeyTypeManager(
      std::unique_ptr<PrimitiveFactory<Primitives>>... primitives)
      : primitive_factories_{std::move(primitives)...} {}

  // Returns the type_url identifying the key type handled by this manager.
  virtual const std::string& get_key_type() const = 0;
  // Returns the version of this key manager.
  virtual uint32_t get_version() const = 0;

  // Returns the key material type for this key type.
  virtual google::crypto::tink::KeyData::KeyMaterialType key_material_type()
      const = 0;

  // Validates the key. Returns util::OkStatus() if the key is valid,
  // and an invalid argument error otherwise.
  virtual util::Status ValidateKey(const KeyProto& key) const = 0;

  // Creates a new primitive using one of the primitive factories passed in at
  // construction time.
  template <typename Primitive>
  util::StatusOr<std::unique_ptr<Primitive>> GetPrimitive(
      const KeyProto& key) const {
    return GetPrimitiveImpl<Primitive>(key);
  }

 private:
  // TODO(C++17) replace with `constexpr if` after migration
  template <typename Primitive>
  typename std::enable_if<
      !internal::OccursInTuple<Primitive, std::tuple<Primitives...>>::value,
      util::StatusOr<std::unique_ptr<Primitive>>>::type
  GetPrimitiveImpl(const KeyProto& key) const {
    return util::Status(
        util::error::INVALID_ARGUMENT,
        absl::StrCat("No PrimitiveFactory was registered for type ",
                     typeid(Primitive).name()));
  }
  template <typename Primitive>
  typename std::enable_if<
      internal::OccursInTuple<Primitive, std::tuple<Primitives...>>::value,
      util::StatusOr<std::unique_ptr<Primitive>>>::type
  GetPrimitiveImpl(const KeyProto& key) const {
    // TODO(C++14) replace with std::get<T> after migration
    constexpr size_t index =
        internal::IndexOf<Primitive, List<Primitives...>>::value;
    return std::get<index>(primitive_factories_)->Create(key);
  }

  std::tuple<std::unique_ptr<PrimitiveFactory<Primitives>>...>
      primitive_factories_;
};

}  // namespace tink
}  // namespace crypto

#endif  // TINK_CORE_KEY_TYPE_MANAGER_H_
