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

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "constants/labels.h"
#include "formats/asset_box.h"
#include "formats/byte_range.h"
#include "formats/gif/constants.h"
#include "formats/gif/reader.h"
#include "jumbf/utils.h"
#include "riegeli/bytes/reader.h"

namespace credentio {

namespace {

constexpr uint64_t kMaxPayloadSize = 10 * 1024 * 1024;  // 10 MiB

absl::StatusOr<std::string> DecodeDataBlocks(absl::string_view data) {
  std::string result;
  result.reserve(data.size());

  for (size_t i = 0; i < data.size();) {
    uint8_t block_size = data[i];
    i++;
    if (block_size == 0) {
      break;
    }
    if (i + block_size > data.size()) {
      return absl::InvalidArgumentError("Invalid block size in GIF C2PA data");
    }
    result.append(data.substr(i, block_size));
    i += block_size;
  }
  return result;
}

}  // namespace

absl::StatusOr<std::string> GifExtractor::ExtractManifestStore(
    riegeli::Reader& input) const {
  ABSL_ASSIGN_OR_RETURN(
      std::optional<ByteRange> c2pa_location,
      ExtractManifestStoreLocation(input, {.requires_c2pa = true}));
  if (!c2pa_location.has_value()) {
    return absl::NotFoundError("No manifest store found");
  }

  // The block starts with two markers identifying it as an application ext.
  // Then there is a single byte identifying the size of the extension info.
  // After that is the extension info itself and then starts the alternating
  // size and data bytes for the manifest store.
  int64_t manifest_data_offset = c2pa_location->offset + 14;
  int64_t manifest_data_length = c2pa_location->length - 14;

  if (manifest_data_length < 0 || manifest_data_length > kMaxPayloadSize) {
    return absl::InvalidArgumentError(
        absl::StrCat("Manifest store is too large: ", manifest_data_length,
                     " > ", kMaxPayloadSize));
  }

  if (!input.Seek(manifest_data_offset)) {
    return input.StatusOrAnnotate(
        absl::InvalidArgumentError("Failed to seek to manifest data offset"));
  }
  std::string encoded_manifest_store;
  if (!input.Read(manifest_data_length, encoded_manifest_store)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("Failed to read manifest data from input"));
  }

  // Data is stored as blocks of size-prefixed data.
  return DecodeDataBlocks(encoded_manifest_store);
}

absl::StatusOr<std::optional<ByteRange>>
GifExtractor::ExtractManifestStoreLocation(riegeli::Reader& input,
                                           ExtractOptions options) const {
  std::optional<GifBlock> c2pa_block = std::nullopt;
  absl::Status iteration_status = IterateOverGifBlocks(
      input,
      [&options, &c2pa_block](const GifBlock& block) -> absl::StatusOr<bool> {
        if (block.offset >= options.end_offset ||
            block.length > options.end_offset - block.offset) {
          // We've gone past the declared end of the input.
          return false;  // stop processing
        }
        if (block.type == kGifImageDescriptorLabel) {
          // The manifest store must be before the first image descriptor.
          // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_embedding_manifests_into_gifs
          return false;  // stop processing
        }
        if (block.type == "C2PA") {
          if (c2pa_block.has_value()) {
            return absl::NotFoundError("Multiple manifest stores found");
          }
          c2pa_block = std::move(block);
        }
        return true;
      },
      options.end_offset);
  ABSL_RETURN_IF_ERROR(iteration_status);
  if (!c2pa_block.has_value()) {
    if (options.requires_c2pa) {
      return absl::NotFoundError("No manifest store found");
    }
    return std::nullopt;
  }
  return ByteRange{.offset = c2pa_block->offset, .length = c2pa_block->length};
}

absl::StatusOr<std::vector<AssetBox>> GifExtractor::ExtractBoxes(
    riegeli::Reader& input, ExtractOptions options) const {
  if (!input.SupportsSize() || !input.Size().has_value()) {
    return absl::InvalidArgumentError(
        "Input does not support size or size is unknown");
  }
  uint64_t end_offset = input.Size().value();
  if (options.end_offset >= 0) {
    end_offset =
        std::min(end_offset, static_cast<uint64_t>(options.end_offset));
  }

  std::vector<AssetBox> blocks;
  bool c2pa_block_found = false;
  absl::Status iteration_status = IterateOverGifBlocks(
      input,
      [&end_offset, &c2pa_block_found,
       &blocks](const GifBlock& block) -> absl::StatusOr<bool> {
        if (block.offset >= end_offset) {
          // The box is past the declared end of the input.
          return false;  // stop processing
        }
        if (block.length > end_offset - block.offset) {
          // The box extends past the declared end of the input.
          if (block.type == "c2pa.after") {
            // We can truncate the c2pa.after block to the end of the input.
            blocks.push_back(AssetBox{
                .identifier = block.type,
                .byte_range = {.offset = block.offset,
                               .length = end_offset - block.offset},
            });
            return false;
          }
          return absl::InvalidArgumentError(
              "Block extends past the declared end of the input");
        }
        if (block.type == "C2PA") {
          if (c2pa_block_found) {
            return absl::NotFoundError("Multiple manifest stores found");
          }
          c2pa_block_found = true;
        }

        blocks.push_back(AssetBox{
            .identifier = block.type,
            .byte_range = {.offset = block.offset, .length = block.length},
        });
        return true;
      },
      end_offset);
  ABSL_RETURN_IF_ERROR(iteration_status);
  if (!c2pa_block_found && options.requires_c2pa) {
    return absl::NotFoundError("No manifest store found");
  }
  return blocks;
}

bool GifExtractor::MightBeC2paManifestStore(absl::string_view payload) const {
  return jumbf::HasDescriptionBoxMatching(payload, kManifestStoreUuid,
                                          kMinimumJumbfDescriptionToggles,
                                          kManifestStoreLabel)
      .value_or(false);
}

}  // namespace credentio
