// 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/png/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/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/notification.h"
#include "async/async_context.h"
#include "crypto/algorithms.h"
#include "formats/png/constants.h"
#include "formats/png/embedder.h"
#include "formats/png/hasher.h"
#include "formats/png/reader.h"
#include "generator/generator.h"
#include "proto/generator.pb.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"

namespace credentio {

PngWriter::PngWriter(const ManifestStoreGenerator* absl_nonnull generator,
                     Options options)
    : generator_(*ABSL_DIE_IF_NULL(generator)), options_(std::move(options)) {}

absl::Status PngWriter::Write(GenerateManifestStoreRequest request,
                              riegeli::Reader* absl_nonnull source,
                              riegeli::Writer* absl_nonnull destination,
                              OutputMetadata* absl_nullable output_metadata) {
  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 PngWriter::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) {
  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 "
        "PngWriter)"));
    return;
  }

  // DigestPng() takes an optional processor over (reader, chunk), so bind the
  // request, which stays alive for the duration of the digest below.
  auto exclusion_fn = [this, &request](riegeli::Reader& reader,
                                       const PngChunk& chunk) {
    return options_.exclusion_processor(reader, chunk, request);
  };
  std::optional<PngExclusionProcessor> exclusion_processor = std::nullopt;
  if (options_.exclusion_processor != nullptr) {
    exclusion_processor.emplace(std::move(exclusion_fn));
  }
  // Hashes the source and reports where the manifest store chunk goes. The
  // hash covers the asset as it will look once that chunk is in place: the
  // chunk itself is recorded as a zero-length exclusion for now, and is sized
  // below once the manifest store template tells us how big it will be.
  auto digest_result =
      DigestPng(*source, HashAlgorithm::kSha256, exclusion_processor);
  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() =
      digest_result->assertion;

  // The manifest store covers its own size, so it is generated in two phases:
  // a template reserves the space, then the exclusions are fixed up to account
  // for it, and only then is the manifest store finalized and embedded.
  generator_.GenerateManifestStoreTemplate(
      request, context,
      [this, source, request, digest_result = std::move(*digest_result),
       destination, output_metadata, context, resolver = std::move(resolver)](
          absl::StatusOr<ManifestStoreTemplate> template_response) mutable {
        if (!template_response.ok()) {
          resolver.Return(template_response.status());
          return;
        }

        constexpr int64_t kMaxManifestStoreSizeBytes =
            100 * 1024 * 1024;  // 100 MiB
        if (template_response->manifest_store_size() <= 0 ||
            template_response->manifest_store_size() >
                kMaxManifestStoreSizeBytes) {
          resolver.Return(absl::InvalidArgumentError(
              absl::StrCat("invalid manifest store template size: ",
                           template_response->manifest_store_size())));
          return;
        }

        FinalizeManifestStoreRequest finalize_request;
        *finalize_request.mutable_manifest_store_template() =
            std::move(*template_response);
        *finalize_request.mutable_hard_binding()->mutable_data_hash() =
            request.hard_binding().data_hash();

        // Size of the whole `caBX` chunk record that will be inserted.
        int64_t embedded_size =
            finalize_request.manifest_store_template().manifest_store_size() +
            kPngChunkLengthSize + kPngChunkTypeC2pa.size() + kPngCrcSize;
        // The exclusions were recorded against the source asset, but they must
        // describe the output asset. Inserting the chunk shifts everything
        // after the insertion point by the size it adds (the size of the new
        // chunk, less any existing `caBX` chunk it replaces), and the
        // placeholder exclusion at the insertion point becomes the chunk.
        for (auto& exclusion : *finalize_request.mutable_hard_binding()
                                    ->mutable_data_hash()
                                    ->mutable_exclusions()) {
          if (exclusion.start() > digest_result.insertion_offset) {
            exclusion.set_start(exclusion.start() + embedded_size -
                                digest_result.existing_c2pa_length.value_or(0));
          } else if (exclusion.start() == digest_result.insertion_offset) {
            exclusion.set_length(embedded_size);
          }
        }

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

              if (output_metadata != nullptr) {
                output_metadata->timestamp_included =
                    finalize_response->is_timestamped();
              }

              PngEmbedder embedder;
              auto status = embedder.CopyAndEmbed(
                  *source, finalize_response->manifest_store(), digest_result,
                  *destination);
              resolver.Return(status);
            });
      });
}

}  // namespace credentio
