// 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/hasher.h"

#include <memory>

#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "bindings/input_hasher.h"
#include "crypto/algorithms.h"
#include "formats/gif/constants.h"
#include "formats/gif/reader.h"
#include "proto/data_hash_assertion.pb.h"
#include "riegeli/bytes/reader.h"

namespace credentio {

absl::StatusOr<DigestGifResult> DigestGif(riegeli::Reader& input,
                                          HashAlgorithm alg) {
  DigestGifResult result = {.insertion_point = {.offset = 0}};

  DataHashAssertion* assertion = &result.data_hash;
  assertion->set_alg(absl::StrCat(alg));

  DataRange* manifest_exclusion = assertion->add_exclusions();
  manifest_exclusion->set_start(0);
  manifest_exclusion->set_length(0);

  bool found_logical_descriptor = false;
  bool found_image_descriptor = false;

  std::unique_ptr<InputHasher> hasher;
  ABSL_ASSIGN_OR_RETURN(hasher, InputHasher::Create(alg));

  ABSL_RETURN_IF_ERROR(IterateOverGifBlocks(
      input,
      [&input, &hasher, &manifest_exclusion, &found_image_descriptor,
       &found_logical_descriptor,
       &result](const GifBlock& block) -> absl::StatusOr<bool> {
        if (block.type == kGifImageDescriptorLabel) {
          found_image_descriptor = true;

          // We reached the Image Descriptor, C2PA must be before this point.
          if (result.insertion_point.offset == 0) {
            return absl::InvalidArgumentError(
                "No location found to insert C2PA block");
          }
        } else if (block.type == kGifLogicalScreenDescriptorLabel) {
          found_logical_descriptor = true;
          // Insert the C2PA block after the logical descriptor.
          result.insertion_point.offset = block.offset + block.length;
          manifest_exclusion->set_start(result.insertion_point.offset);
        } else if (block.type == "C2PA") {
          if (result.existing_c2pa_length.has_value()) {
            // This means that the asset has multiple C2PA blocks.
            return absl::InvalidArgumentError(
                "Unexpected additional C2PA block found");
          }
          if (found_image_descriptor) {
            return absl::InvalidArgumentError(
                "Unexpected C2PA block found after Image Descriptor");
          }
          if (!found_logical_descriptor) {
            return absl::InvalidArgumentError(
                "Unexpected C2PA block found before Logical Descriptor");
          }

          // Replace the existing C2PA block instead
          result.insertion_point.offset = block.offset;
          result.existing_c2pa_length = block.length;

          manifest_exclusion->set_start(block.offset);
          // Don't update the hash for the existing C2PA block.
          return true;
        }

        ABSL_RETURN_IF_ERROR(hasher->Update(input, block.offset, block.length));
        return true;
      }));

  if (result.insertion_point.offset == 0 || !found_logical_descriptor) {
    return absl::InvalidArgumentError(
        "No Logical Screen Descriptor found in GIF");
  }

  // Set the hash
  assertion->set_hash(hasher->Digest());
  return result;
}

}  // namespace credentio
