// 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);
  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();

  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, source_size, request,
                                 options_.exclusion_processor, assertion));

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

  uint32_t file_size_after_ifd =
      source_size + 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(source_size +       // Existing file size
                               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,
    };
    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
