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

#include <algorithm>
#include <cstdint>
#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/substitute.h"
#include "formats/riff/chunk_header.h"
#include "riegeli/bytes/reader.h"

namespace credentio {

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

absl::StatusOr<bool> IterateOverRiffChunksInternal(
    riegeli::Reader& reader, uint64_t end_offset,
    RiffChunkProcessor processor) {
  while (reader.pos() + ChunkHeader::header_size() <= end_offset) {
    uint64_t chunk_offset = reader.pos();
    ChunkHeader chunk_header;
    ABSL_RETURN_IF_ERROR(chunk_header.Read(reader));

    RiffChunk chunk = {
        .offset = chunk_offset,
        .length = chunk_header.chunk_size(),
        .id = chunk_header.id,
        .type = "",
        .data_offset = chunk_offset + chunk_header.header_size(),
        .data_length = chunk_header.data_size,
    };

    if (chunk.HasSubchunks()) {
      if (chunk.data_length < 4) {
        return absl::InvalidArgumentError(
            "RIFF/LIST chunk too short to contain a form type");
      }
      if (!reader.Read(4, chunk.type)) {
        return reader.StatusOrAnnotate(
            absl::DataLossError("kUnexpectedEof; type"));
      }
      chunk.data_offset += 4;
      chunk.data_length -= 4;
    }

    if (chunk.length < ChunkHeader::header_size()) {
      return absl::InvalidArgumentError("Invalid RIFF chunk size");
    }
    if (chunk.length > end_offset - chunk.offset) {
      return absl::InvalidArgumentError(
          "RIFF chunk extends beyond the end of the file");
    }
    uint64_t chunk_end_offset = chunk.offset + chunk.length;

    bool continue_processing;
    if (auto result = processor(chunk); result.ok()) {
      continue_processing = *result;
    } else {
      return result.status();
    }
    if (!continue_processing) {
      return false;
    }

    if (reader.pos() < chunk.data_offset + chunk.data_length &&
        chunk.HasSubchunks()) {
      if (auto sub_continue_or = IterateOverRiffChunksInternal(
              reader, chunk_end_offset, processor);
          sub_continue_or.ok()) {
        continue_processing = *sub_continue_or;
      } else {
        return sub_continue_or.status();
      }
      if (!continue_processing) {
        return false;
      }
    }

    reader.Seek(chunk_end_offset);
    if (reader.pos() <= chunk_offset) {
      return absl::InternalError(
          "RIFF parser detected a read stall (infinite loop prevented)");
    }
  }
  return true;
}

}  // namespace

absl::Status IterateOverRiffChunks(riegeli::Reader& reader,
                                   RiffChunkProcessor processor,
                                   int64_t end_offset) {
  if (!reader.SupportsSize() || !reader.Size().has_value()) {
    return absl::InvalidArgumentError(
        "manifest store not embedded: reader size cannot be determined");
  }
  uint64_t actual_end_offset =
      end_offset < 0 ? *reader.Size()
                     : std::min(static_cast<uint64_t>(*reader.Size()),
                                static_cast<uint64_t>(end_offset));

  if ((actual_end_offset - reader.pos()) == 0) {
    return absl::OkStatus();
  }

  return IterateOverRiffChunksInternal(reader, actual_end_offset, processor)
      .status();
}

absl::StatusOr<std::string> ReadRiffChunkData(riegeli::Reader& reader,
                                              const RiffChunk& chunk) {
  if (IsRiffChunkTooLarge(chunk)) {
    return absl::InvalidArgumentError(
        absl::Substitute("RIFF C2PA chunk is too large to extract ($0 > $1)",
                         chunk.data_length, kMaxPayloadSize));
  }

  if (reader.pos() != chunk.data_offset) {
    if (!reader.Seek(chunk.data_offset) || reader.pos() != chunk.data_offset) {
      return absl::InvalidArgumentError("Failed to seek to chunk data offset");
    }
  }

  std::string data;
  if (!reader.Read(chunk.data_length, data)) {
    return reader.StatusOrAnnotate(absl::DataLossError("kUnexpectedEof; data"));
  }
  return std::move(data);
}

bool IsRiffChunkTooLarge(const RiffChunk& chunk) {
  return chunk.data_length > kMaxPayloadSize;
}

}  // namespace credentio
