// 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 "formats/gif/writer.h"

#include <cstdint>
#include <optional>
#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/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/notification.h"
#include "async/async_context.h"
#include "crypto/algorithms.h"
#include "formats/gif/block.h"
#include "formats/gif/embedder.h"
#include "formats/gif/hasher.h"
#include "generator/generator.h"
#include "proto/data_hash_assertion.pb.h"
#include "proto/generator.pb.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"

namespace credentio {
namespace {

void AdjustDataHashExclusions(DataHashAssertion* absl_nonnull assertion,
                              int64_t c2pa_offset, int64_t c2pa_size) {
  for (auto& exclusion : *assertion->mutable_exclusions()) {
    if (exclusion.start() < c2pa_offset) {
      // Before the C2PA segment, so no adjustment needed.
      continue;
    }
    if (exclusion.start() == c2pa_offset) {
      // This is the C2PA segment, just need to fill in the length.
      exclusion.set_length(c2pa_size);
      continue;
    }
    // This is after the C2PA segment, so we need to add the manifest size to
    // the offset.
    exclusion.set_start(exclusion.start() + c2pa_size);
  }
}

absl::Status CopyAndEmbed(riegeli::Reader& input,
                          absl::string_view manifest_store,
                          int64_t insert_at_offset,
                          std::optional<int64_t> existing_c2pa_length,
                          riegeli::Writer& destination) {
  if (!input.Seek(0)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("failed to seek to start of input"));
  }
  GifEmbedder embedder;
  ABSL_RETURN_IF_ERROR(
      embedder.CopyAndEmbed(input, manifest_store, insert_at_offset,
                            existing_c2pa_length, destination));
  return absl::OkStatus();
}

}  // namespace

GifWriter::GifWriter(const ManifestStoreGenerator* absl_nonnull generator)
    : generator_(*ABSL_DIE_IF_NULL(generator)) {}

absl::Status GifWriter::Write(
    GenerateManifestStoreRequest request, riegeli::Reader* absl_nonnull source,
    riegeli::Writer* absl_nonnull destination,
    OutputMetadata* absl_nullable output_metadata) const {
  absl::Notification done;
  absl::Status status;
  Write(std::move(request), source, destination, output_metadata,
        AsyncContext(), [&](absl::Status s) {
          status = std::move(s);
          done.Notify();
        });
  done.WaitForNotification();
  return status;
}

void GifWriter::Write(GenerateManifestStoreRequest request,
                      riegeli::Reader* absl_nonnull source,
                      riegeli::Writer* absl_nonnull destination,
                      OutputMetadata* absl_nullable output_metadata,
                      AsyncContext context,
                      absl::AnyInvocable<void(absl::Status) &&> cb) const {
  AsyncResolver<void> resolver(context, std::move(cb));
  if (request.has_hard_binding()) {
    resolver.Return(absl::InvalidArgumentError(
        "request must not include `hard_binding` (binding is computed by "
        "GifWriter)"));
    return;
  }

  auto digest_result = DigestGif(*source, HashAlgorithm::kSha256);
  if (!digest_result.ok()) {
    resolver.Return(digest_result.status());
    return;
  }

  if (digest_result->existing_c2pa_length.has_value() &&
      (!request.has_actions() || !request.actions().has_opened())) {
    resolver.Return(absl::AlreadyExistsError(
        "C2PA chunk already exists, but no `opened` action was provided"));
    return;
  }

  request.mutable_hard_binding()->mutable_data_hash()->Swap(
      &digest_result->data_hash);
  auto insertion_point = std::move(digest_result->insertion_point);
  auto existing_c2pa_length = digest_result->existing_c2pa_length;

  generator_.GenerateManifestStoreTemplate(
      request, context,
      [generator = &generator_, source, request,
       insertion_point = std::move(insertion_point), existing_c2pa_length,
       destination, output_metadata, context, resolver = std::move(resolver)](
          absl::StatusOr<ManifestStoreTemplate> template_response) mutable {
        if (!template_response.ok()) {
          resolver.Return(template_response.status());
          return;
        }

        uint64_t embedded_size = CalculateTotalGifC2paBlockSize(
            template_response->manifest_store_size());

        FinalizeManifestStoreRequest finalize_request;
        finalize_request.mutable_manifest_store_template()->Swap(
            &*template_response);
        finalize_request.mutable_hard_binding()->MergeFrom(
            request.hard_binding());

        AdjustDataHashExclusions(
            finalize_request.mutable_hard_binding()->mutable_data_hash(),
            insertion_point.offset, embedded_size);

        generator->FinalizeManifestStore(
            finalize_request, context,
            [source, insertion_point, existing_c2pa_length, destination,
             output_metadata, resolver = std::move(resolver)](
                absl::StatusOr<FinalizeManifestStoreResponse>
                    finalize_response) mutable {
              if (!finalize_response.ok()) {
                resolver.Return(finalize_response.status());
                return;
              }

              auto copy_status = CopyAndEmbed(
                  *source, finalize_response->manifest_store(),
                  insertion_point.offset, existing_c2pa_length, *destination);
              if (!copy_status.ok()) {
                resolver.Return(std::move(copy_status));
                return;
              }
              if (output_metadata != nullptr) {
                output_metadata->timestamp_included =
                    finalize_response->is_timestamped();
              }
              resolver.Return(absl::OkStatus());
            });
      });
}

}  // namespace credentio
