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

#include <memory>
#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "claim/local_signer.h"
#include "crypto/crypto_write_handler.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "crypto/templated_crypto_write_handler.h"
#include "formats/bmff/writer.h"
#include "formats/gif/writer.h"
#include "formats/id3/writer.h"
#include "formats/jpeg/writer.h"
#include "formats/pdf/writer.h"
#include "formats/png/writer.h"
#include "formats/riff/writer.h"
#include "formats/tiff/writer.h"
#include "formats/zip/writer.h"
#include "generator/generator.h"
#include "generator/generator_factory.h"
#include "generator/generator_options.h"
#include "proto/generator.pb.h"
#include "riegeli/bytes/cfile_reader.h"
#include "riegeli/bytes/cfile_writer.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"
#include "testing/local_key_crypto_write_handler.h"
#include "utils/media_type.h"

namespace credentio {

absl::Status WriteAsset(LocalKeyCryptoWriteHandlerOptions crypto_options,
                        GenerateManifestStoreRequest request,
                        absl::string_view media_type, riegeli::Reader& source,
                        riegeli::Writer& destination) {
  ABSL_ASSIGN_OR_RETURN(
      std::unique_ptr<CryptoWriteHandler> crypto_write_handler,
      CreateLocalKeyCryptoWriteHandler(std::move(crypto_options)));

  const HasherFactory& hash_factory = DefaultHasherFactory();
  TemplatedHasherFactory template_hash_factory(hash_factory.algorithm());
  TemplatedCryptoWriteHandler template_crypto_write_handler(
      crypto_write_handler.get());

  LocalClaimSigner template_claim_signer(&template_crypto_write_handler,
                                         &template_hash_factory);
  LocalClaimSigner signing_claim_signer(crypto_write_handler.get(),
                                        &hash_factory);

  GeneratorOptions generator_options;
  generator_options.generator_info.set_name("c2pa_asset_write");
  generator_options.signing_claim_signer = &signing_claim_signer;
  generator_options.template_claim_signer = &template_claim_signer;
  generator_options.hash_factory = &hash_factory;

  ABSL_ASSIGN_OR_RETURN(std::unique_ptr<ManifestStoreGenerator> generator,
                        CreateGenerator(std::move(generator_options)));

  if (!request.has_actions()) {
    request.mutable_actions()->mutable_created();
  }

  if (media_type == "image/png") {
    PngWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination,
                        /*output_metadata=*/nullptr);
  }
  if (media_type == "image/jpeg") {
    JpegWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination,
                        /*output_metadata=*/nullptr);
  }
  if (media_type == "image/gif") {
    GifWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination,
                        /*output_metadata=*/nullptr);
  }
  if (media_type == "video/mp4" || media_type == "video/quicktime" ||
      media_type == "image/heic" || media_type == "image/heif" ||
      media_type == "image/avif" || media_type == "audio/mp4") {
    BmffWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination,
                        /*output_metadata=*/nullptr);
  }
  if (media_type == "image/tiff" || media_type == "image/tiff-fx" ||
      media_type == "image/x-adobe-dng") {
    TiffWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination,
                        /*output_metadata=*/nullptr);
  }
  if (media_type == "image/webp" || media_type == "audio/wav" ||
      media_type == "audio/x-wav" || media_type == "audio/vnd.wave" ||
      media_type == "video/x-msvideo" || media_type == "video/avi") {
    RiffWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination,
                        /*output_metadata=*/nullptr);
  }
  if (media_type == "audio/mpeg" || media_type == "audio/mp3" ||
      media_type == "audio/flac" || media_type == "audio/x-flac") {
    Id3Writer writer(generator.get());
    return writer.Write(std::move(request), &source, &destination);
  }
  if (media_type == "application/pdf") {
    PdfWriter writer(generator.get());
    return writer.Write(std::move(request), &source, &destination);
  }
  if (media_type == "application/zip" ||
      media_type ==
          "application/"
          "vnd.openxmlformats-officedocument.presentationml.presentation" ||
      media_type ==
          "application/"
          "vnd.openxmlformats-officedocument.wordprocessingml.document" ||
      media_type ==
          "application/"
          "vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
    ZipWriter writer(generator.get());
    return writer.Write(request, &source, &destination);
  }

  return absl::UnimplementedError(
      absl::StrCat("Unsupported media type for asset_write: ", media_type));
}

absl::Status WriteAssetFile(LocalKeyCryptoWriteHandlerOptions crypto_options,
                            GenerateManifestStoreRequest request,
                            absl::string_view input_path,
                            absl::string_view output_path) {
  // Writing in place would truncate the input asset before it is read.
  if (input_path == output_path) {
    return absl::InvalidArgumentError(absl::StrCat(
        "In-place writing is not supported; the output path must differ from "
        "the input path: ",
        input_path));
  }

  ABSL_ASSIGN_OR_RETURN(std::string media_type, MediaType(input_path));

  riegeli::CFileReader<> source(input_path);
  if (!source.ok()) {
    return source.status();
  }

  // Some writers (e.g. `ZipWriter`) read back the destination, so it must be
  // opened for reading as well.
  riegeli::CFileWriter<> destination(
      output_path, riegeli::CFileWriterBase::Options().set_read(true));
  if (!destination.ok()) {
    return destination.status();
  }

  ABSL_RETURN_IF_ERROR(WriteAsset(std::move(crypto_options), std::move(request),
                                  media_type, source, destination));

  if (!source.Close()) {
    return source.status();
  }
  if (!destination.Close()) {
    return destination.status();
  }
  return absl::OkStatus();
}

}  // namespace credentio
