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

#include <sys/types.h>

#include <cstdint>
#include <optional>
#include <vector>

#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 "formats/byte_range.h"
#include "formats/tiff/constants.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/endian/endian_reading.h"

namespace credentio {
namespace {
template <typename T>
absl::Status ReadNumber(riegeli::Reader& source, TiffEndianness endianness,
                        T& value) {
  bool success = endianness == TiffEndianness::kBigEndian
                     ? riegeli::ReadBigEndian<T>(source, value)
                     : riegeli::ReadLittleEndian<T>(source, value);
  if (!success) {
    return source.StatusOrAnnotate(absl::DataLossError("failed to read value"));
  }
  return absl::OkStatus();
}

absl::StatusOr<TiffEndianness> GetEndianness(riegeli::Reader& source) {
  uint32_t header;
  if (!riegeli::ReadBigEndian<uint32_t>(source, header)) {
    return source.StatusOrAnnotate(
        absl::DataLossError("kUnexpectedEof; endianness"));
  }
  switch (header) {
    case kTiffBigEndianHeader:
      return TiffEndianness::kBigEndian;
    case kTiffLittleEndianHeader:
      return TiffEndianness::kLittleEndian;
    default:
      return absl::DataLossError("invalid endianness");
  }
}

}  // namespace

ByteRange TiffImageFileDirectoryEntry::RangeOfCount() const {
  return ByteRange{.offset = offset + sizeof(uint16_t) + sizeof(uint16_t),
                   .length = sizeof(uint32_t)};
}

ByteRange TiffImageFileDirectoryEntry::RangeOfValue() const {
  uint64_t value_size = size();

  return ByteRange{.offset = value_size > sizeof(uint32_t)
                                 ? value_or_offset
                                 : offset + sizeof(uint16_t) +
                                       sizeof(uint16_t) + sizeof(uint32_t),
                   .length = value_size};
}

absl::Status IterateOverImageFileDirectories(
    riegeli::Reader& source, std::optional<TiffEndianness> known_endianness,
    absl::flat_hash_set<uint32_t>& visited_offsets,
    ImageFileDirectoryProcessor process_ifd) {
  TiffEndianness endianness;
  if (known_endianness.has_value()) {
    endianness = *known_endianness;
  } else {
    ABSL_ASSIGN_OR_RETURN(endianness, GetEndianness(source));
  }

  while (true) {
    TiffImageFileDirectory ifd{.offset_of_pointer =
                                   static_cast<uint32_t>(source.pos())};

    uint32_t offset;
    ABSL_RETURN_IF_ERROR(ReadNumber(source, endianness, offset));
    ifd.offset = offset;

    if (!visited_offsets.insert(offset).second) {
      return absl::InvalidArgumentError("infinite loop detected");
    }

    if (!source.Seek(offset)) {
      return source.StatusOrAnnotate(absl::InternalError(
          absl::StrCat("Failed to seek to offset: ", offset)));
    }

    uint16_t count;
    ABSL_RETURN_IF_ERROR(ReadNumber(source, endianness, count));
    ifd.entries.resize(count);
    for (int i = 0; i < count; ++i) {
      TiffImageFileDirectoryEntry& entry = ifd.entries[i];
      entry.offset = source.pos();
      ABSL_RETURN_IF_ERROR(ReadNumber(source, endianness, entry.tag));
      ABSL_RETURN_IF_ERROR(ReadNumber(source, endianness, entry.type));
      ABSL_RETURN_IF_ERROR(ReadNumber(source, endianness, entry.count));
      ABSL_RETURN_IF_ERROR(
          ReadNumber(source, endianness, entry.value_or_offset));
    }

    uint64_t next_offset_position = source.pos();

    ABSL_ASSIGN_OR_RETURN(bool continue_processing,
                          process_ifd(ifd, endianness));

    if (!continue_processing) {
      break;
    }

    if (!source.Seek(next_offset_position)) {
      return source.StatusOrAnnotate(absl::InternalError(
          absl::StrCat("Failed to seek to offset: ", next_offset_position)));
    }

    uint32_t next_offset;
    ABSL_RETURN_IF_ERROR(ReadNumber(source, endianness, next_offset));

    if (!source.Seek(next_offset_position)) {
      return source.StatusOrAnnotate(absl::InternalError(
          absl::StrCat("Failed to seek to offset: ", next_offset_position)));
    }

    if (next_offset == 0) {
      break;
    }
  }

  return absl::OkStatus();
}

}  // namespace credentio
