// Copyright 2025 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdint.h>

#include <vector>

#include "testing/gtest/include/gtest/gtest.h"
#include "testing/png_codec/png_codec.h"

namespace png_codec {

namespace {

// Test helper to decode `input` bytes into RGBA output, expecting a 1x1 image.
//
// When successful, a vector of exactly 4 bytes is returned.
// An empty vector indicates that an error has occurred.
std::vector<uint8_t> Decode1x1PNGToRGBA(pdfium::span<const uint8_t> input) {
  constexpr bool kReverseByteOrder = false;  // This asks for RGBA output.

  int output_width = -1;
  int output_height = -1;
  std::vector<uint8_t> rgba_output =
      Decode(input, kReverseByteOrder, &output_width, &output_height);
  EXPECT_EQ(output_height, 1);
  EXPECT_EQ(output_width, 1);
  return rgba_output;
}

}  // namespace

TEST(PngCodec, EncodeBGRAAndDiscardTransparency) {
  const std::vector<uint8_t> bgrx_input = {1, 2, 3, /*ignored_alpha=*/4};
  std::vector<uint8_t> png = EncodeBGRA(bgrx_input,
                                        /*width=*/1,
                                        /*height=*/1,
                                        /*row_byte_width=*/4,
                                        /*discard_transparency=*/true);
  ASSERT_FALSE(png.empty());

  std::vector<uint8_t> rgba_output = Decode1x1PNGToRGBA(png);
  ASSERT_EQ(rgba_output.size(), 4u);

  // Verifying that the RGB / BGR pixels are preserved.
  EXPECT_EQ(rgba_output[0], bgrx_input[2]);
  EXPECT_EQ(rgba_output[1], bgrx_input[1]);
  EXPECT_EQ(rgba_output[2], bgrx_input[0]);

  // Verifying that the decoded pixels are fully opaque
  // (i.e. that the `4` in input got discarded / ignored).
  EXPECT_EQ(rgba_output[3], 255);
}

TEST(PngCodec, EncodeBGRAAndPreserveTransparency) {
  const std::vector<uint8_t> bgra_input = {1, 2, 3, 4};
  std::vector<uint8_t> png = EncodeBGRA(bgra_input,
                                        /*width=*/1,
                                        /*height=*/1,
                                        /*row_byte_width=*/4,
                                        /*discard_transparency=*/false);
  ASSERT_FALSE(png.empty());

  std::vector<uint8_t> rgba_output = Decode1x1PNGToRGBA(png);
  ASSERT_EQ(rgba_output.size(), 4u);

  // Verifying that all the RGBA / BGRA pixels are preserved.
  EXPECT_EQ(rgba_output[0], bgra_input[2]);
  EXPECT_EQ(rgba_output[1], bgra_input[1]);
  EXPECT_EQ(rgba_output[2], bgra_input[0]);
  EXPECT_EQ(rgba_output[3], bgra_input[3]);
}

TEST(PngCodec, EncodeBGR) {
  std::vector<uint8_t> bgr_input = {1, 2, 3};
  std::vector<uint8_t> png = EncodeBGR(bgr_input,
                                       /*width=*/1,
                                       /*height=*/1,
                                       /*row_byte_width=*/3);
  ASSERT_FALSE(png.empty());

  std::vector<uint8_t> rgba_output = Decode1x1PNGToRGBA(png);
  ASSERT_EQ(rgba_output.size(), 4u);

  // Verifying that all the RGB / BGR pixels are preserved.
  EXPECT_EQ(rgba_output[0], bgr_input[2]);
  EXPECT_EQ(rgba_output[1], bgr_input[1]);
  EXPECT_EQ(rgba_output[2], bgr_input[0]);

  // Verifying that alpha is opaque.
  EXPECT_EQ(rgba_output[3], 255);
}

TEST(PngCodec, EncodeRGBA) {
  std::vector<uint8_t> rgba_input = {1, 2, 3, 4};
  std::vector<uint8_t> png = EncodeRGBA(rgba_input,
                                        /*width=*/1,
                                        /*height=*/1,
                                        /*row_byte_width=*/4);
  ASSERT_FALSE(png.empty());

  std::vector<uint8_t> rgba_output = Decode1x1PNGToRGBA(png);
  ASSERT_EQ(rgba_output.size(), 4u);

  // Verifying that all the RGBA values are preserved.
  EXPECT_EQ(rgba_output[0], rgba_input[0]);
  EXPECT_EQ(rgba_output[1], rgba_input[1]);
  EXPECT_EQ(rgba_output[2], rgba_input[2]);
  EXPECT_EQ(rgba_output[3], rgba_input[3]);
}

TEST(PngCodec, EncodeGray) {
  std::vector<uint8_t> grayscale_input = {123};
  std::vector<uint8_t> png = EncodeGray(grayscale_input,
                                        /*width=*/1,
                                        /*height=*/1,
                                        /*row_byte_width=*/1);
  ASSERT_FALSE(png.empty());

  std::vector<uint8_t> rgba_output = Decode1x1PNGToRGBA(png);
  ASSERT_EQ(rgba_output.size(), 4u);

  // Verifying that all the RGBA values correspond to the input.
  EXPECT_EQ(rgba_output[0], grayscale_input[0]);  // R=gray
  EXPECT_EQ(rgba_output[1], grayscale_input[0]);  // G=gray
  EXPECT_EQ(rgba_output[2], grayscale_input[0]);  // B=gray
  EXPECT_EQ(rgba_output[3], 255);                 // A=opaque
}

}  // namespace png_codec
