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

#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#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 "absl/types/span.h"
#include "bindings/input_hasher.h"
#include "crypto/algorithms.h"
#include "formats/byte_range.h"
#include "formats/tiff/constants.h"
#include "formats/tiff/hasher.h"
#include "formats/tiff/reader.h"
#include "google/protobuf/repeated_ptr_field.h"
#include "proto/data_hash_assertion.pb.h"
#include "proto/generator.pb.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/string_writer.h"
#include "riegeli/bytes/writer.h"
#include "riegeli/endian/endian_writing.h"
#include "utils/byte_instruction.h"

namespace credentio {
namespace {

// The maximum number of entries per IFD in a TIFF file.
constexpr uint16_t kTiffMaxEntriesPerIfd = 60000;

template <typename T>
absl::Status WriteEndian(T value, TiffEndianness endianness,
                         riegeli::Writer& writer) {
  const bool success = endianness == TiffEndianness::kBigEndian
                           ? riegeli::WriteBigEndian<T>(value, writer)
                           : riegeli::WriteLittleEndian<T>(value, writer);

  return success ? absl::OkStatus()
                 : writer.StatusOrAnnotate(
                       absl::InternalError("Failed to write value"));
}

struct ArtifactInformation {
  TiffImageFileDirectory ifd_to_add_to;
  TiffEndianness endianness;
};

// Scans the TIFF file for the first IFD that can be used to store the C2PA
// data. If no suitable IFD is found, a new IFD will be created at the end of
// the file. Returns an error if a C2PA entry already exists.
absl::StatusOr<ArtifactInformation> ScanForArtifactInformation(
    riegeli::Reader& source, uint32_t file_size,
    const GenerateManifestStoreRequest& request,
    const TiffWriter::ExclusionProcessor& exclusion_processor,
    DataHashAssertion* absl_nonnull assertion) {
  ArtifactInformation result;

  absl::flat_hash_set<uint32_t> visited_offsets;
  ABSL_RETURN_IF_ERROR(IterateOverImageFileDirectories(
      source, /*known_endianness=*/std::nullopt, visited_offsets,
      [&result, &request, &exclusion_processor, assertion, &source,
       &visited_offsets](const TiffImageFileDirectory& ifd,
                         TiffEndianness endianness) -> absl::StatusOr<bool> {
        for (const TiffImageFileDirectoryEntry& entry : ifd.entries) {
          if (entry.tag == kTiffTagC2pa) {
            return absl::AlreadyExistsError("C2PA entry already exists");
          }
          if (exclusion_processor != nullptr) {
            ABSL_ASSIGN_OR_RETURN(
                std::vector<ByteRange> exclusions,
                exclusion_processor(source, entry, endianness, visited_offsets,
                                    request));
            for (const ByteRange& exclusion_range : exclusions) {
              auto* exclusion = assertion->add_exclusions();
              exclusion->set_start(exclusion_range.offset);
              exclusion->set_length(exclusion_range.length);
            }
          }
        }

        result.endianness = endianness;
        result.ifd_to_add_to = ifd;
        return true;
      }));

  if (result.ifd_to_add_to.offset_of_pointer != 4 ||
      result.ifd_to_add_to.entries.size() >= kTiffMaxEntriesPerIfd) {
    // Need to insert a new IFD at the end of the file
    result.ifd_to_add_to = TiffImageFileDirectory{
        .offset_of_pointer = static_cast<uint32_t>(source.pos()),
        .offset = file_size,
    };
  }

  return result;
}

template <typename T>
absl::Status AppendNumberToString(T value, TiffEndianness endianness,
                                  std::string& output) {
  riegeli::StringWriter writer(
      &output, riegeli::StringWriterBase::Options().set_append(true));

  const bool success = endianness == TiffEndianness::kBigEndian
                           ? riegeli::WriteBigEndian<T>(value, writer)
                           : riegeli::WriteLittleEndian<T>(value, writer);
  if (!success) {
    return writer.StatusOrAnnotate(
        absl::InternalError("Failed to write value"));
  }
  if (!writer.Close()) {
    return writer.StatusOrAnnotate(
        absl::InternalError("Failed to close writer"));
  }
  return absl::OkStatus();
}

// Adjusts the pointer to the IFD to point to the new location. If the IFD is
// being moved, zero out the original location.
absl::StatusOr<std::vector<ByteInstruction>>
CreateByteInstructionsForIfdInsertion(
    const TiffImageFileDirectory& ifd_to_add_to, TiffEndianness endianness,
    uint32_t file_size) {
  std::vector<ByteInstruction> byte_instructions;

  // Add a byte instruction to update pointer to the IFD.
  byte_instructions.push_back(ByteInstruction{
      .operation = ByteInstruction::Operation::kReplace,
      .offset = ifd_to_add_to.offset_of_pointer,
  });
  ABSL_RETURN_IF_ERROR(AppendNumberToString<uint32_t>(
      file_size, endianness, byte_instructions.back().bytes));

  if (ifd_to_add_to.offset_of_pointer == 4) {
    // C2PA data will be written to the first (and only) IFD, it will be moved
    // to the end of the file, zero out the original location.
    byte_instructions.push_back(ByteInstruction{
        .operation = ByteInstruction::Operation::kReplace,
        .offset = ifd_to_add_to.offset,
        .bytes = std::string(
            ByteSizeOfImageFileDirectory(ifd_to_add_to.entries.size()), '\0'),
    });
  }
  return std::move(byte_instructions);
}

void SanitizeExclusions(
    google::protobuf::RepeatedPtrField<DataRange>* exclusions) {
  if (exclusions->empty()) return;
  std::sort(exclusions->pointer_begin(), exclusions->pointer_end(),
            [](const DataRange* a, const DataRange* b) {
              if (a->start() != b->start()) return a->start() < b->start();
              return a->length() < b->length();
            });

  google::protobuf::RepeatedPtrField<DataRange> merged;
  DataRange current = (*exclusions)[0];
  for (int i = 1; i < exclusions->size(); ++i) {
    const DataRange& next = (*exclusions)[i];
    uint64_t current_end = current.start() + current.length();
    uint64_t next_end = next.start() + next.length();
    if (next.start() <= current_end) {
      if (next_end > current_end) {
        current.set_length(next_end - current.start());
      }
    } else {
      *merged.Add() = current;
      current = next;
    }
  }
  *merged.Add() = current;
  exclusions->Swap(&merged);
}

absl::Status HashAroundExclusion(const DataRange& exclusion,
                                 riegeli::Reader& source, InputHasher& hasher) {
  if (exclusion.start() < source.pos()) {
    return absl::InvalidArgumentError(
        "Exclusion start is before current source position");
  }
  // Hash up to the start of the exclusion.
  uint64_t hash_length = exclusion.start() - source.pos();
  ABSL_RETURN_IF_ERROR(ReadHash(source, hash_length, hasher));

  // Skip the excluded data
  if (!source.Skip(exclusion.length())) {
    return absl::InternalError("failed to skip data");
  }

  return absl::OkStatus();
}

absl::Status HashInstructionAroundExclusion(const DataRange& exclusion,
                                            uint64_t instruction_offset,
                                            absl::string_view instruction_bytes,
                                            InputHasher& hasher) {
  if (exclusion.start() < instruction_offset ||
      exclusion.start() - instruction_offset > instruction_bytes.size()) {
    return absl::InvalidArgumentError(
        "Exclusion range out of bounds of byte instruction");
  }

  // hash until the exclusion offset
  absl::string_view data_to_hash =
      instruction_bytes.substr(0, exclusion.start() - instruction_offset);
  hasher.Update(data_to_hash);

  if (exclusion.length() >
      instruction_bytes.size() - (exclusion.start() - instruction_offset)) {
    return absl::InvalidArgumentError(
        "Exclusion data out of bounds of byte instruction");
  }

  return absl::OkStatus();
}

absl::Status Hash(riegeli::Reader& source, uint64_t length_with_ifd,
                  absl::Span<const ByteInstruction> byte_instructions,
                  const DataHashAssertion& assertion, InputHasher& hasher) {
  auto exclusion_iter = assertion.exclusions().begin();

  for (const ByteInstruction& ins : byte_instructions) {
    while (exclusion_iter->start() < ins.offset) {
      ABSL_RETURN_IF_ERROR(
          HashAroundExclusion(*exclusion_iter, source, hasher));
      ++exclusion_iter;
      if (exclusion_iter == assertion.exclusions().end()) {
        return absl::InternalError("ran out of exclusions");
      }
    }
    // Next exclusion is after the start of the instruction, hash up to the
    // instruction offset.
    if (ins.offset < source.pos()) {
      return absl::InvalidArgumentError(
          "Byte instruction offset is before current source position");
    }
    ABSL_RETURN_IF_ERROR(ReadHash(source, ins.offset - source.pos(), hasher));

    uint64_t ins_processed = 0;
    while (exclusion_iter->start() < ins.offset + ins.bytes.size()) {
      ABSL_RETURN_IF_ERROR(HashInstructionAroundExclusion(
          *exclusion_iter, ins.offset + ins_processed,
          absl::string_view(ins.bytes).substr(ins_processed), hasher));

      ins_processed =
          (exclusion_iter->start() + exclusion_iter->length()) - ins.offset;

      ++exclusion_iter;
      if (exclusion_iter == assertion.exclusions().end()) {
        return absl::InternalError("ran out of exclusions");
      }
    }

    // Process remaining instruction bytes
    if (ins_processed < ins.bytes.size()) {
      absl::string_view data_to_hash =
          absl::string_view(ins.bytes).substr(ins_processed);
      hasher.Update(data_to_hash);
    }

    if (ins.operation == ByteInstruction::Operation::kReplace) {
      if (!source.Skip(ins.bytes.size())) {
        return absl::InternalError("failed to skip data");
      }
    }
  }

  return absl::OkStatus();
}

absl::Status WriteImageFileDirectory(
    absl::Span<const TiffImageFileDirectoryEntry> entries,
    TiffEndianness endianness, riegeli::Writer& writer) {
  // Entry Count
  ABSL_RETURN_IF_ERROR(
      WriteEndian<uint16_t>(entries.size(), endianness, writer));
  // Entries
  for (const auto& entry : entries) {
    ABSL_RETURN_IF_ERROR(WriteEndian<uint16_t>(entry.tag, endianness, writer));
    ABSL_RETURN_IF_ERROR(WriteEndian<uint16_t>(entry.type, endianness, writer));
    ABSL_RETURN_IF_ERROR(
        WriteEndian<uint32_t>(entry.count, endianness, writer));
    ABSL_RETURN_IF_ERROR(
        WriteEndian<uint32_t>(entry.value_or_offset, endianness, writer));
  }
  // Next IFD Offset
  ABSL_RETURN_IF_ERROR(WriteEndian<uint32_t>(0, endianness, writer));
  return absl::OkStatus();
}

absl::Status WriteImageFileDirectory(
    absl::Span<const TiffImageFileDirectoryEntry> entries,
    TiffEndianness endianness, std::string& destination) {
  riegeli::StringWriter<> writer(
      &destination, riegeli::StringWriterBase::Options().set_append(true));
  ABSL_RETURN_IF_ERROR(WriteImageFileDirectory(entries, endianness, writer));
  if (!writer.Close()) {
    return writer.status();
  }
  return absl::OkStatus();
}

}  // namespace

absl::StatusOr<std::vector<ByteInstruction>> TiffWriter::WriteInternal(
    GenerateManifestStoreRequest request, riegeli::Reader* absl_nonnull source,
    OutputMetadata* absl_nullable output_metadata) const {
  if (request.has_hard_binding()) {
    return absl::InvalidArgumentError(
        "request must not include `hard_binding` (binding is computed by "
        "TiffWriter)");
  }
  if (!source->SupportsSize()) {
    return absl::InvalidArgumentError("source must support Size()");
  }
  if (!source->Size().has_value()) {
    return absl::InternalError("source->Size() returned no value");
  }

  uint64_t source_size = *source->Size();
  uint64_t padding_size = source_size % 2;
  uint64_t ifd_offset = source_size + padding_size;

  auto hash_algorithm = HashAlgorithm::kSha256;

  auto* assertion = request.mutable_hard_binding()->mutable_data_hash();
  assertion->set_alg(absl::StrCat(hash_algorithm));
  assertion->set_hash(std::string(32, '\0'));

  ABSL_ASSIGN_OR_RETURN(
      ArtifactInformation artifact_information,
      ScanForArtifactInformation(*source, ifd_offset, request,
                                 options_.exclusion_processor, assertion));

  ABSL_ASSIGN_OR_RETURN(std::vector<ByteInstruction> byte_instructions,
                        CreateByteInstructionsForIfdInsertion(
                            artifact_information.ifd_to_add_to,
                            artifact_information.endianness, ifd_offset));

  uint32_t file_size_after_ifd =
      ifd_offset + ByteSizeOfImageFileDirectory(
                       artifact_information.ifd_to_add_to.entries.size() + 1);

  artifact_information.ifd_to_add_to.entries.push_back(
      TiffImageFileDirectoryEntry{
          .tag = kTiffTagC2pa,
          .type = kTiffTypeUndefined,
          .count = 1,
          .value_or_offset = file_size_after_ifd,
      });

  std::sort(artifact_information.ifd_to_add_to.entries.begin(),
            artifact_information.ifd_to_add_to.entries.end(),
            [](const TiffImageFileDirectoryEntry& a,
               const TiffImageFileDirectoryEntry& b) { return a.tag < b.tag; });

  {
    // Holder for the C2PA IFD entry count.
    auto* count_exclusion = assertion->add_exclusions();
    // IFD count, IFD Entry tag, and IFD Entry type are 3 uint16_t's

    uint16_t c2pa_entry_index = 0;
    for (const auto& entry : artifact_information.ifd_to_add_to.entries) {
      if (entry.tag == kTiffTagC2pa) {
        break;
      }
      ++c2pa_entry_index;
    }

    count_exclusion->set_start(ifd_offset +        // Offset of relocated IFD
                               sizeof(uint16_t) +  // final IFD count
                               // Number of entries before C2PA entry
                               (c2pa_entry_index * kTiffIfdEntrySize) +
                               sizeof(uint16_t) +   // C2PA entry tag
                               sizeof(uint16_t));   // C2PA entry type
    count_exclusion->set_length(sizeof(uint32_t));  // C2PA entry count

    // Holder for the Manifest Store.
    auto* length_exclusion = assertion->add_exclusions();
    // Will be located after the IFD containing the C2PA data.
    length_exclusion->set_start(file_size_after_ifd);
    length_exclusion->set_length(1);
  }

  SanitizeExclusions(assertion->mutable_exclusions());

  ABSL_ASSIGN_OR_RETURN(auto template_response,
                        generator_.GenerateManifestStoreTemplate(request));

  if ((std::numeric_limits<uint32_t>::max() - file_size_after_ifd -
       template_response.manifest_store_size()) < 0) {
    return absl::InvalidArgumentError(
        "Manifest store size is too large (not enough space for TIFF "
        "structure)");
  }

  // Update the length exclusion to the actual length of the manifest store.
  assertion->mutable_exclusions()->rbegin()->set_length(
      template_response.manifest_store_size());
  for (auto& entry : artifact_information.ifd_to_add_to.entries) {
    if (entry.tag == kTiffTagC2pa) {
      entry.count = template_response.manifest_store_size();
      break;
    }
  }

  {
    ByteInstruction last_ifd{
        .operation = ByteInstruction::Operation::kInsert,
        .offset = source_size,
        .bytes = std::string(padding_size, '\0'),
    };
    ABSL_RETURN_IF_ERROR(WriteImageFileDirectory(
        artifact_information.ifd_to_add_to.entries,
        artifact_information.endianness, last_ifd.bytes));
    byte_instructions.push_back(last_ifd);
  }

  std::sort(byte_instructions.begin(), byte_instructions.end(),
            [](const ByteInstruction& a, const ByteInstruction& b) {
              return a.offset < b.offset;
            });

  source->Seek(0);

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

  ABSL_RETURN_IF_ERROR(Hash(*source, file_size_after_ifd, byte_instructions,
                            *assertion, *hasher));

  FinalizeManifestStoreRequest finalize_request;
  *finalize_request.mutable_manifest_store_template() =
      std::move(template_response);
  *finalize_request.mutable_hard_binding()->mutable_data_hash() =
      request.hard_binding().data_hash();
  finalize_request.mutable_hard_binding()->mutable_data_hash()->set_hash(
      hasher->Digest());

  ABSL_ASSIGN_OR_RETURN(auto finalize_response,
                        generator_.FinalizeManifestStore(finalize_request));

  byte_instructions.push_back(
      ByteInstruction{.operation = ByteInstruction::Operation::kInsert,
                      .offset = static_cast<uint64_t>(file_size_after_ifd),
                      .bytes = finalize_response.manifest_store()});

  std::sort(byte_instructions.begin(), byte_instructions.end(),
            [](const ByteInstruction& a, const ByteInstruction& b) {
              return a.offset < b.offset;
            });

  if (output_metadata != nullptr) {
    output_metadata->timestamp_included = finalize_response.is_timestamped();
  }

  return byte_instructions;
}

absl::Status TiffWriter::Write(
    GenerateManifestStoreRequest request, riegeli::Reader* absl_nonnull source,
    riegeli::Writer* absl_nonnull destination,
    OutputMetadata* absl_nullable output_metadata) const {
  ABSL_ASSIGN_OR_RETURN(
      auto byte_instructions,
      WriteInternal(std::move(request), source, output_metadata));

  return ApplyByteInstructions(source, byte_instructions, destination);
}

absl::Status TiffWriter::Write(
    GenerateManifestStoreRequest request, riegeli::Writer* absl_nonnull asset,
    OutputMetadata* absl_nullable output_metadata) const {
  if (!asset->SupportsRandomAccess()) {
    return absl::InvalidArgumentError("asset must support RandomAccess()");
  }
  if (!asset->SupportsReadMode()) {
    return absl::InvalidArgumentError("asset must support ReadMode()");
  }

  riegeli::Reader* source = asset->ReadMode(0);
  if (source == nullptr) {
    return absl::InternalError("Failed to switch asset to ReadMode");
  }

  ABSL_ASSIGN_OR_RETURN(
      auto byte_instructions,
      WriteInternal(std::move(request), source, output_metadata));

  return ApplyByteInstructions(byte_instructions, asset);
}

}  // namespace credentio
