// Copyright 2026 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
//
//    https://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.
//

#include "claim/generator.h"

#include <memory>
#include <utility>

#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/die_if_null.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "assertion/assertion_cbor_encoder.h"
#include "assertion/assertion_referencer.h"
#include "async/async_context.h"
#include "claim/claim_cbor_encoder.h"
#include "claim/manifest_box.h"
#include "claim/manifest_box_assembler.h"
#include "claim/manifest_box_encoder.h"
#include "claim/signer.h"
#include "crypto/hash.h"
#include "proto/actions_assertion.pb.h"
#include "proto/assertion.pb.h"
#include "proto/bmff_based_hash_assertion.pb.h"
#include "proto/boxes_hash_assertion.pb.h"
#include "proto/data_hash_assertion.pb.h"
#include "proto/generator.pb.h"
#include "proto/generator_info.pb.h"
#include "proto/hashed_uri.pb.h"
#include "proto/manifest.pb.h"
#include "salt/salt_generator.h"

namespace credentio {
namespace {

ClaimSigner::Options ToClaimSignerOptions(
    const GenerateManifestStoreOptions& options, AsyncContext context) {
  ClaimSigner::Options result;
  result.async_context = std::move(context);
  switch (options.time_stamping_mode()) {
    case GenerateManifestStoreOptions::TIME_STAMPING_REQUIRED:
      result.time_stamping_mode = TimeStampingMode::kRequired;
      break;
    case GenerateManifestStoreOptions::TIME_STAMPING_OMITTED_WITH_PADDING:
      result.time_stamping_mode = TimeStampingMode::kOmittedWithPadding;
      break;
    case GenerateManifestStoreOptions::TIME_STAMPING_OPTIONAL:
    case GenerateManifestStoreOptions::TIME_STAMPING_MODE_UNSPECIFIED:
    default:
      result.time_stamping_mode = TimeStampingMode::kOptional;
      break;
  }
  return result;
}

class ManifestEncoderImpl : public ManifestEncoder {
 public:
  explicit ManifestEncoderImpl(
      GeneratorInfo generator_info,
      const HasherFactory* absl_nonnull hash_factory,
      ClaimSigner* absl_nonnull claim_signer,
      const AssertionCborEncoder* absl_nonnull assertion_cbor_encoder,
      const ClaimCborEncoder* absl_nonnull claim_cbor_encoder,
      const SaltGenerator* absl_nonnull salt_generator)
      : generator_info_(std::move(generator_info)),
        hash_factory_(*ABSL_DIE_IF_NULL(hash_factory)),
        claim_signer_(*ABSL_DIE_IF_NULL(claim_signer)),
        assertion_cbor_encoder_(*ABSL_DIE_IF_NULL(assertion_cbor_encoder)),
        claim_cbor_encoder_(*ABSL_DIE_IF_NULL(claim_cbor_encoder)),
        salt_generator_(*ABSL_DIE_IF_NULL(salt_generator)) {}

  void Encode(ManifestBox* absl_nonnull manifest,
              const GenerateManifestStoreOptions& options, AsyncContext context,
              absl::AnyInvocable<void(absl::StatusOr<ManifestEncoderResult>) &&>
                  cb) const override {
    auto assertion_reference =
        std::make_shared<AssertionReferencer>(&hash_factory_);
    auto manifest_box_encoder = std::make_shared<ManifestBoxEncoder>(
        assertion_reference.get(), &generator_info_, &claim_signer_,
        &assertion_cbor_encoder_, &claim_cbor_encoder_, manifest,
        hash_factory_.algorithm(), &salt_generator_);
    manifest_box_encoder->Encode(
        ToClaimSignerOptions(options, std::move(context)),
        [assertion_reference, manifest_box_encoder, cb = std::move(cb)](
            absl::StatusOr<ManifestEncoderResult> result) mutable {
          std::move(cb)(std::move(result));
        });
  }

 private:
  GeneratorInfo generator_info_;
  const HasherFactory& hash_factory_;
  ClaimSigner& claim_signer_;
  const AssertionCborEncoder& assertion_cbor_encoder_;
  const ClaimCborEncoder& claim_cbor_encoder_;
  const SaltGenerator& salt_generator_;
};
}  // namespace

absl::StatusOr<std::unique_ptr<ManifestBoxAssembler>> CreateManifestAssembler(
    const CreateManifestAssemblerOptions& options) {
  return std::make_unique<StandardManifestBoxAssembler>(
      options.uuid_generator, options.hash_factory, options.spec_version);
}

absl::StatusOr<std::unique_ptr<ManifestEncoder>> CreateManifestEncoder(
    const CreateManifestEncoderOptions& options) {
  return std::make_unique<ManifestEncoderImpl>(
      options.generator_info, options.hash_factory, options.claim_signer,
      options.assertion_cbor_encoder, options.claim_cbor_encoder,
      options.salt_generator);
}
}  // namespace credentio
