// SPDX-License-Identifier: GPL-2.0-or-later

#ifndef PNGCHUNK_INT_HPP_
#define PNGCHUNK_INT_HPP_

// *****************************************************************************
// included header files
#include "pngimage.hpp"
#include "types.hpp"

// *****************************************************************************
// namespace extensions
namespace Exiv2::Internal {
// *****************************************************************************
// class definitions

/*!
  @brief Stateless parser class for data in PNG chunk format. Images use this
         class to decode and encode PNG-based data.
 */
class PngChunk {
 public:
  /*!
    @brief Text Chunk types.
  */
  enum TxtChunkType { tEXt_Chunk = 0, zTXt_Chunk = 1, iTXt_Chunk = 2 };

  /*!
    @brief Decode PNG IHDR chunk data from a data buffer
           \em data and return image size to \em outWidth and \em outHeight.

    @param data      PNG Chunk data buffer.
    @param outWidth  Integer pointer to be set to the width of the image.
    @param outHeight Integer pointer to be set to the height of the image.
  */
  static void decodeIHDRChunk(const DataBuf& data, uint32_t* outWidth, uint32_t* outHeight);

  /*!
    @brief Decode PNG tEXt, zTXt, or iTXt chunk data from \em pImage passed by data buffer
           \em data and extract Comment, Exif, Iptc, Xmp metadata accordingly.

    @param pImage    Pointer to the image to hold the metadata
    @param data      PNG Chunk data buffer.
    @param type      PNG Chunk TXT type.
  */
  static void decodeTXTChunk(Image* pImage, const DataBuf& data, TxtChunkType type);

  /*!
   @brief Decode PNG tEXt, zTXt, or iTXt chunk data from \em pImage passed by data buffer
   \em data and extract Comment, Exif, Iptc, Xmp to DataBuf

   @param data      PNG Chunk data buffer.
   @param type      PNG Chunk TXT type.
   */
  static DataBuf decodeTXTChunk(const DataBuf& data, TxtChunkType type);

  /*!
    @brief Return PNG TXT chunk key as data buffer.

    @param data        PNG Chunk data buffer.
    @param stripHeader Set true if chunk data start with header bytes, else false (default).
  */
  static DataBuf keyTXTChunk(const DataBuf& data, bool stripHeader = false);

  /*!
    @brief Return a complete PNG chunk data compressed or not as buffer.
           Data returned is formatted accordingly with metadata \em type
           to host passed by \em metadata.

    @param metadata    metadata buffer.
    @param type        metadata type.
  */
  static std::string makeMetadataChunk(const std::string& metadata, MetadataId type);

 private:
  /*!
    @brief Parse PNG Text chunk to determine type and extract content.
           Supported Chunk types are tTXt, zTXt, and iTXt.
   */
  static DataBuf parseTXTChunk(const DataBuf& data, size_t keysize, TxtChunkType type);

  /*!
    @brief Parse PNG chunk contents to extract metadata container and assign it to image.
           Supported contents are:
              Exif raw text profile generated by ImageMagick ==> Image Exif metadata.
              Iptc raw text profile generated by ImageMagick ==> Image Iptc metadata.
              Xmp  raw text profile generated by ImageMagick ==> Image Xmp metadata.
              Xmp  packet generated by Adobe                 ==> Image Xmp metadata.
              Description string                             ==> Image Comments.
   */
  static void parseChunkContent(Image* pImage, const byte* key, size_t keySize, const DataBuf& arr);

  /*!
    @brief Return a compressed (zTXt) or uncompressed (tEXt) PNG ASCII text chunk
           (length + chunk type + chunk data + CRC) as a string.

    @param keyword  Keyword for the PNG text chunk
    @param text     Text to be recorded in the PNG chunk.
    @param compress Flag indicating whether to compress the PNG chunk data.

    @return String containing the PNG chunk
  */
  static std::string makeAsciiTxtChunk(const std::string& keyword, const std::string& text, bool compress);

  /*!
    @brief Return a compressed or uncompressed (iTXt) PNG international text chunk
           (length + chunk type + chunk data + CRC) as a string.

    @param keyword  Keyword for the PNG international text chunk
    @param text     Text to be recorded in the PNG chunk.
    @param compress Flag indicating whether to compress the PNG chunk data.
  */
  static std::string makeUtf8TxtChunk(const std::string& keyword, const std::string& text, bool compress);

  /*!
    @brief Wrapper around zlib to uncompress a PNG chunk content.
   */
  static void zlibUncompress(const byte* compressedText, unsigned int compressedTextSize, DataBuf& arr);

  /*!
    @brief Wrapper around zlib to compress a PNG chunk content.
   */
  static std::string zlibCompress(const std::string& text);

  /*!
    @brief Decode from ImageMagick raw text profile which host encoded Exif/Iptc/Xmp metadata byte array.
   */
  static DataBuf readRawProfile(const DataBuf& text, bool iTXt);

  /*!
    @brief Encode to ImageMagick raw text profile, which host encoded
           Exif/IPTC/XMP metadata byte arrays.
   */
  static std::string writeRawProfile(const std::string& profileData, const char* profileType);

  friend class Exiv2::PngImage;

};  // class PngChunk

}  // namespace Exiv2::Internal

#endif  // #ifndef PNGCHUNK_INT_HPP_
