// 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.
//

// TIFF Format Information:
//   https://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.pdf
// C2PA embedding:
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_embedding_manifests_into_tiff_based_assets
#include "formats/tiff/extractor.h"

#include <sys/types.h>

#include <cstdint>
#include <optional>
#include <string>
#include <utility>

#include "absl/container/flat_hash_set.h"
#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/byte_range.h"
#include "formats/tiff/constants.h"
#include "formats/tiff/reader.h"
#include "jumbf/utils.h"
#include "riegeli/bytes/reader.h"

namespace credentio {

namespace {

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

absl::StatusOr<std::optional<ByteRange>> FindManifestStore(
    riegeli::Reader& source) {
  absl::flat_hash_set<uint32_t> visited_offsets;

  std::optional<ByteRange> manifest_store_location = std::nullopt;
  bool reading_first_ifd = true;
  absl::Status iteration_status = IterateOverImageFileDirectories(
      source, std::nullopt, visited_offsets,
      [&reading_first_ifd, &manifest_store_location](
          const TiffImageFileDirectory& ifd,
          TiffEndianness endianness) -> absl::StatusOr<bool> {
        // A previous loop found a manifest store.
        if (manifest_store_location.has_value()) {
          return absl::NotFoundError("Manifest Store must be in the last IFD");
        }

        for (const TiffImageFileDirectoryEntry& entry : ifd.entries) {
          if (entry.tag != kTiffTagC2pa) {
            continue;
          }

          if (!reading_first_ifd && ifd.entries.size() != 1) {
            return absl::NotFoundError(
                "Manifest Store must be the only entry in the IFD");
          }

          if (manifest_store_location.has_value()) {
            return absl::NotFoundError("Multiple manifest stores found");
          }

          manifest_store_location = entry.RangeOfValue();
        }

        reading_first_ifd = false;
        return true;
      });
  ABSL_RETURN_IF_ERROR(iteration_status);
  return manifest_store_location;
}

bool IsPartialAsset(int64_t current_offset, int64_t end_offset,
                    int64_t asset_size) {
  if (end_offset == -1) {
    // Not a windowed read, so not partial.
    return false;
  }
  if (current_offset == 0 && end_offset == asset_size) {
    // The window covers the entire asset, so it is not partial.
    return false;
  }
  return true;
}

}  // namespace

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

  if (location->length > kMaxPayloadSize) {
    return absl::InvalidArgumentError(
        absl::StrCat("Manifest store is too large: ", location->length, " > ",
                     kMaxPayloadSize));
  }

  if (!input.Seek(location->offset)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("Failed to seek to offset"));
  }

  std::string manifest_store;
  if (!input.Read(location->length, manifest_store)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("Failed to read manifest store"));
  }
  return std::move(manifest_store);
}

absl::StatusOr<std::optional<ByteRange>>
TiffExtractor::ExtractManifestStoreLocation(riegeli::Reader& input,
                                            ExtractOptions options) const {
  if (IsPartialAsset(input.pos(), options.end_offset,
                     input.Size().value_or(0))) {
    return absl::InvalidArgumentError(
        "TiffExtractor::ExtractManifestStoreLocation only supports operations "
        "over the entire file.");
  }

  if (!input.Seek(0)) {
    return input.StatusOrAnnotate(
        absl::DataLossError("Failed to seek to offset"));
  }

  ABSL_ASSIGN_OR_RETURN(auto result, FindManifestStore(input));
  if (!options.requires_c2pa) {
    return result;
  }
  if (!result.has_value()) {
    return absl::NotFoundError("No manifest store found");
  }
  return result;
}

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

}  // namespace credentio
