// 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_MANAGER_IMPL_H_
#define TINK_CORE_KEY_MANAGER_IMPL_H_

#include "absl/base/casts.h"
#include "tink/core/key_type_manager.h"
#include "tink/key_manager.h"
#include "tink/util/constants.h"
#include "tink/util/status.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {
namespace internal {

// Template declaration of the class "KeyFactoryImpl" with a single template
// argument. We first declare it, then later give two "partial template
// specializations". This will imply that the KeyFactoryImpl can only be
// instantiated with arguments of the form KeyTypeManager<...>.
template <class KeyTypeManager>
class KeyFactoryImpl;

// First partial template specialization for KeyFactoryImpl: the given
// KeyTypeManager is of the form KeyTypeManager<KeyProto,
// KeyFormatProto, List<Primitives...>>.
template <class KeyProto, class KeyFormatProto, class... Primitives>
class KeyFactoryImpl<
    KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>>
    : public KeyFactory {
 public:
  explicit KeyFactoryImpl(KeyTypeManager<KeyProto, KeyFormatProto,
                                         List<Primitives...>>* key_type_manager)
      : key_type_manager_(key_type_manager) {}

  crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
  NewKey(const portable_proto::MessageLite& key_format) const override {
    if (key_format.GetTypeName() != KeyFormatProto().GetTypeName()) {
      return crypto::tink::util::Status(
          util::error::INVALID_ARGUMENT,
          absl::StrCat("Key format proto '", key_format.GetTypeName(),
                       "' is not supported by this manager."));
    }
    auto validation = key_type_manager_->ValidateKeyFormat(
        static_cast<const KeyFormatProto&>(key_format));
    if (!validation.ok()) {
      return validation;
    }
    crypto::tink::util::StatusOr<KeyProto> new_key_result =
        key_type_manager_->CreateKey(
            static_cast<const KeyFormatProto&>(key_format));
    if (!new_key_result.ok()) return new_key_result.status();
    return absl::implicit_cast<std::unique_ptr<portable_proto::MessageLite>>(
        absl::make_unique<KeyProto>(std::move(new_key_result.ValueOrDie())));
  }

  crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
  NewKey(absl::string_view serialized_key_format) const override {
    KeyFormatProto key_format;
    if (!key_format.ParseFromString(std::string(serialized_key_format))) {
      return crypto::tink::util::Status(
          util::error::INVALID_ARGUMENT,
          absl::StrCat("Could not parse the passed string as proto '",
                       KeyFormatProto().GetTypeName(), "'."));
    }
    auto validation = key_type_manager_->ValidateKeyFormat(key_format);
    if (!validation.ok()) {
      return validation;
    }
    return NewKey(static_cast<const portable_proto::MessageLite&>(key_format));
  }

  crypto::tink::util::StatusOr<std::unique_ptr<google::crypto::tink::KeyData>>
  NewKeyData(absl::string_view serialized_key_format) const override {
    auto new_key_result = NewKey(serialized_key_format);
    if (!new_key_result.ok()) return new_key_result.status();
    auto new_key = static_cast<const KeyProto&>(*(new_key_result.ValueOrDie()));
    auto key_data = absl::make_unique<google::crypto::tink::KeyData>();
    key_data->set_type_url(
        absl::StrCat(kTypeGoogleapisCom, KeyProto().GetTypeName()));
    key_data->set_value(new_key.SerializeAsString());
    key_data->set_key_material_type(key_type_manager_->key_material_type());
    return std::move(key_data);
  }

 private:
  KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
      key_type_manager_;
};

// Second partial template specialization for KeyFactoryImpl: the given
// KeyTypeManager is of the form KeyTypeManager<KeyProto, void,
// List<Primitives...>>.
template <class KeyProto, class... Primitives>
class KeyFactoryImpl<KeyTypeManager<KeyProto, void, List<Primitives...>>>
    : public KeyFactory {
 public:
  // We don't need the KeyTypeManager, but this is called from a template,
  // so the easiest way to ignore the argument is to provide a constructor which
  // ignores the argument.
  explicit KeyFactoryImpl(
      KeyTypeManager<KeyProto, void, List<Primitives...>>* key_type_manager) {}

  crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
  NewKey(const portable_proto::MessageLite& key_format) const override {
    return util::Status(
        util::error::UNIMPLEMENTED,
        "Creating new keys is not supported for this key manager.");
  }

  crypto::tink::util::StatusOr<std::unique_ptr<portable_proto::MessageLite>>
  NewKey(absl::string_view serialized_key_format) const override {
    return util::Status(
        util::error::UNIMPLEMENTED,
        "Creating new keys is not supported for this key manager.");
  }

  crypto::tink::util::StatusOr<std::unique_ptr<google::crypto::tink::KeyData>>
  NewKeyData(absl::string_view serialized_key_format) const override {
    return util::Status(
        util::error::UNIMPLEMENTED,
        "Creating new keys is not supported for this key manager.");
  }
};

// Template declaration of the class "KeyManagerImpl" with two template
// arguments. There is only one specialization which is defined, namely when
// the KeyTypeManager argument is of the form KeyTypeManager<KeyProto,
// KeyFormatProto, List<Primitives...>>. We don't provide a
// specialization for the case KeyFormatProto = void, so the compiler will pick
// this instantiation in this case.
template <class Primitive, class KeyTypeManager>
class KeyManagerImpl;

// The first template argument to the KeyManagerImpl is the primitive for which
// we should generate a KeyManager. The second is the KeyTypeManager, which
// takes itself template arguments. The list of the Primitives there must
// contain the first Primitive argument (otherwise there will be failures at
// runtime).
template <class Primitive, class KeyProto, class KeyFormatProto,
          class... Primitives>
class KeyManagerImpl<
    Primitive, KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>>
    : public KeyManager<Primitive> {
 public:
  explicit KeyManagerImpl(KeyTypeManager<KeyProto, KeyFormatProto,
                                         List<Primitives...>>* key_type_manager)
      : key_type_manager_(key_type_manager),
        key_factory_(
            absl::make_unique<KeyFactoryImpl<
                KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>>>(
                key_type_manager_)) {}

  // Constructs an instance of Primitive for the given 'key_data'.
  crypto::tink::util::StatusOr<std::unique_ptr<Primitive>> GetPrimitive(
      const google::crypto::tink::KeyData& key_data) const override {
    if (!this->DoesSupport(key_data.type_url())) {
      return ToStatusF(util::error::INVALID_ARGUMENT,
                       "Key type '%s' is not supported by this manager.",
                       key_data.type_url().c_str());
    }
    KeyProto key_proto;
    if (!key_proto.ParseFromString(key_data.value())) {
      return ToStatusF(util::error::INVALID_ARGUMENT,
                       "Could not parse key_data.value as key type '%s'.",
                       key_data.type_url().c_str());
    }
    auto validation = key_type_manager_->ValidateKey(key_proto);
    if (!validation.ok()) {
      return validation;
    }
    return key_type_manager_->template GetPrimitive<Primitive>(key_proto);
  }

  crypto::tink::util::StatusOr<std::unique_ptr<Primitive>> GetPrimitive(
      const portable_proto::MessageLite& key) const override {
    std::string key_type = absl::StrCat(kTypeGoogleapisCom, key.GetTypeName());
    if (!this->DoesSupport(key_type)) {
      return ToStatusF(util::error::INVALID_ARGUMENT,
                       "Key type '%s' is not supported by this manager.",
                       key_type.c_str());
    }
    const KeyProto& key_proto = static_cast<const KeyProto&>(key);
    auto validation = key_type_manager_->ValidateKey(key_proto);
    if (!validation.ok()) {
      return validation;
    }
    return key_type_manager_->template GetPrimitive<Primitive>(key_proto);
  }

  uint32_t get_version() const override {
    return key_type_manager_->get_version();
  }

  const std::string& get_key_type() const override {
    return key_type_manager_->get_key_type();
  }

  const KeyFactory& get_key_factory() const override {
    return *key_factory_;
  }

 private:
  KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
      key_type_manager_;
  std::unique_ptr<KeyFactory> key_factory_;
};

// Helper function to create a KeyManager<Primitive> from a KeyTypeManager.
// Using this, all template arguments except the first one can be infered.
// Example:
//   std::unique_ptr<KeyManager<Aead>> km =
//     MakeKeyManager<Aead>(my_key_type_manager.get());
template <class Primitive, class KeyProto, class KeyFormatProto,
          class... Primitives>
std::unique_ptr<KeyManager<Primitive>> MakeKeyManager(
    KeyTypeManager<KeyProto, KeyFormatProto, List<Primitives...>>*
        key_type_manager) {
  return absl::make_unique<
      KeyManagerImpl<Primitive, KeyTypeManager<KeyProto, KeyFormatProto,
                                               List<Primitives...>>>>(
      key_type_manager);
}

}  // namespace internal
}  // namespace tink
}  // namespace crypto

#endif  // TINK_CORE_KEY_MANAGER_IMPL_H_
