// Copyright 2024 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#include <cstdint>

#include "avif/avif.h"
#include "avif/avif_cxx.h"
#include "avif/internal.h"
#include "gtest/gtest.h"

namespace avif {
namespace {

//------------------------------------------------------------------------------

class AvifExpression : public avifSampleTransformExpression {
 public:
  AvifExpression() : avifSampleTransformExpression{} {}
  ~AvifExpression() { avifArrayDestroy(this); }

  void AddConstant(int32_t constant) {
    avifSampleTransformToken& token = AddToken();
    token.type = AVIF_SAMPLE_TRANSFORM_CONSTANT;
    token.constant = constant;
  }
  void AddImage(uint8_t inputImageItemIndex) {
    avifSampleTransformToken& token = AddToken();
    token.type = AVIF_SAMPLE_TRANSFORM_INPUT_IMAGE_ITEM_INDEX;
    token.inputImageItemIndex = inputImageItemIndex;
  }
  void AddOperator(avifSampleTransformTokenType op) {
    avifSampleTransformToken& token = AddToken();
    token.type = static_cast<uint8_t>(op);
  }

  int32_t Apply() const {
    ImagePtr result(avifImageCreate(/*width=*/1, /*height=*/1, /*depth=*/8,
                                    AVIF_PIXEL_FORMAT_YUV444));
    if (result.get() == nullptr) abort();
    if (avifImageAllocatePlanes(result.get(), AVIF_PLANES_YUV) !=
        AVIF_RESULT_OK) {
      abort();
    }

    if (avifImageApplyExpression(result.get(),
                                 AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_32, this,
                                 /*numInputImageItems=*/0, nullptr,
                                 AVIF_PLANES_YUV) != AVIF_RESULT_OK) {
      abort();
    }
    return result->yuvPlanes[0][0];
  }

 private:
  avifSampleTransformToken& AddToken() {
    if (tokens == nullptr &&
        !avifArrayCreate(this, sizeof(avifSampleTransformToken), 1)) {
      abort();
    }
    avifSampleTransformToken* token =
        reinterpret_cast<avifSampleTransformToken*>(avifArrayPush(this));
    if (token == nullptr) abort();
    return *token;
  }
};

//------------------------------------------------------------------------------

TEST(SampleTransformTest, NoExpression) {
  AvifExpression empty;
  ASSERT_EQ(
      avifSampleTransformRecipeToExpression(AVIF_SAMPLE_TRANSFORM_NONE, &empty),
      AVIF_RESULT_INVALID_ARGUMENT);
  EXPECT_TRUE(avifSampleTransformExpressionIsEquivalentTo(&empty, &empty));
}

TEST(SampleTransformTest, NoRecipe) {
  AvifExpression empty;
  avifSampleTransformRecipe recipe;
  ASSERT_EQ(avifSampleTransformExpressionToRecipe(&empty, &recipe),
            AVIF_RESULT_OK);
  EXPECT_EQ(recipe, AVIF_SAMPLE_TRANSFORM_NONE);
}

TEST(SampleTransformTest, RecipeToExpression) {
  for (avifSampleTransformRecipe recipe :
       {AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_8B_8B,
        AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_12B_4B,
        AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_12B_8B_OVERLAP_4B}) {
    AvifExpression expression;
    ASSERT_EQ(avifSampleTransformRecipeToExpression(recipe, &expression),
              AVIF_RESULT_OK);
    avifSampleTransformRecipe result;
    ASSERT_EQ(avifSampleTransformExpressionToRecipe(&expression, &result),
              AVIF_RESULT_OK);
    EXPECT_EQ(recipe, result);

    EXPECT_FALSE(avifSampleTransformExpressionIsValid(
        &expression, /*numInputImageItems=*/1));
    EXPECT_TRUE(avifSampleTransformExpressionIsValid(&expression,
                                                     /*numInputImageItems=*/2));
    EXPECT_TRUE(avifSampleTransformExpressionIsValid(&expression,
                                                     /*numInputImageItems=*/3));

    EXPECT_TRUE(
        avifSampleTransformExpressionIsEquivalentTo(&expression, &expression));
  }
}

TEST(SampleTransformTest, NotEquivalent) {
  AvifExpression a;
  ASSERT_EQ(avifSampleTransformRecipeToExpression(
                AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_8B_8B, &a),
            AVIF_RESULT_OK);

  AvifExpression b;
  ASSERT_EQ(avifSampleTransformRecipeToExpression(
                AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_12B_4B, &b),
            AVIF_RESULT_OK);

  EXPECT_FALSE(avifSampleTransformExpressionIsEquivalentTo(&a, &b));
}

TEST(SampleTransformTest, MaxStackSize) {
  AvifExpression e;
  for (int i = 0; i < 128; ++i) e.AddConstant(42);
  for (int i = 0; i < 127; ++i) e.AddOperator(AVIF_SAMPLE_TRANSFORM_SUM);

  EXPECT_EQ(e.Apply(), 255);
}

//------------------------------------------------------------------------------

struct Op {
  Op(int32_t l, avifSampleTransformTokenType o, int32_t r, uint32_t e)
      : left(l), right(r), op(o), expected_result(e), single_operand(false) {}
  Op(avifSampleTransformTokenType o, int32_t l, uint32_t e)
      : left(l), right(0), op(o), expected_result(e), single_operand(true) {}

  int32_t left;
  int32_t right;
  avifSampleTransformTokenType op;
  uint32_t expected_result;
  bool single_operand;
};

class SampleTransformOperationTest : public testing::TestWithParam<Op> {};

TEST_P(SampleTransformOperationTest, Apply) {
  AvifExpression expression;
  // Postfix notation.
  expression.AddConstant(GetParam().left);
  if (!GetParam().single_operand) expression.AddConstant(GetParam().right);
  expression.AddOperator(GetParam().op);

  EXPECT_EQ(expression.Apply(), GetParam().expected_result);
}

INSTANTIATE_TEST_SUITE_P(
    Operations, SampleTransformOperationTest,
    testing::Values(Op(AVIF_SAMPLE_TRANSFORM_NEGATE, 1, 0),
                    Op(AVIF_SAMPLE_TRANSFORM_NEGATE, -1, 1),
                    Op(AVIF_SAMPLE_TRANSFORM_NEGATE, 0, 0),
                    Op(AVIF_SAMPLE_TRANSFORM_NEGATE, -256, 255),
                    Op(AVIF_SAMPLE_TRANSFORM_ABSOLUTE, 1, 1),
                    Op(AVIF_SAMPLE_TRANSFORM_ABSOLUTE, -1, 1),
                    Op(AVIF_SAMPLE_TRANSFORM_ABSOLUTE, 256, 255),
                    Op(AVIF_SAMPLE_TRANSFORM_ABSOLUTE, -256, 255),
                    Op(1, AVIF_SAMPLE_TRANSFORM_SUM, 1, 2),
                    Op(255, AVIF_SAMPLE_TRANSFORM_SUM, 255, 255),
                    Op(1, AVIF_SAMPLE_TRANSFORM_DIFFERENCE, 1, 0),
                    Op(255, AVIF_SAMPLE_TRANSFORM_DIFFERENCE, 255, 0),
                    Op(255, AVIF_SAMPLE_TRANSFORM_DIFFERENCE, 0, 255),
                    Op(0, AVIF_SAMPLE_TRANSFORM_DIFFERENCE, 255, 0),
                    Op(1, AVIF_SAMPLE_TRANSFORM_DIFFERENCE, -1, 2),
                    Op(-1, AVIF_SAMPLE_TRANSFORM_DIFFERENCE, 1, 0),
                    Op(1, AVIF_SAMPLE_TRANSFORM_PRODUCT, 1, 1),
                    Op(2, AVIF_SAMPLE_TRANSFORM_PRODUCT, 3, 6),
                    Op(1, AVIF_SAMPLE_TRANSFORM_DIVIDE, 1, 1),
                    Op(2, AVIF_SAMPLE_TRANSFORM_DIVIDE, 3, 0),
                    Op(1, AVIF_SAMPLE_TRANSFORM_AND, 1, 1),
                    Op(1, AVIF_SAMPLE_TRANSFORM_AND, 2, 0),
                    Op(7, AVIF_SAMPLE_TRANSFORM_AND, 15, 7),
                    Op(1, AVIF_SAMPLE_TRANSFORM_OR, 1, 1),
                    Op(1, AVIF_SAMPLE_TRANSFORM_OR, 2, 3),
                    Op(1, AVIF_SAMPLE_TRANSFORM_XOR, 3, 2),
                    Op(AVIF_SAMPLE_TRANSFORM_NOT, 254, 0),
                    Op(AVIF_SAMPLE_TRANSFORM_NOT, -1, 0),
                    Op(AVIF_SAMPLE_TRANSFORM_MSB, 0, 0),
                    Op(AVIF_SAMPLE_TRANSFORM_MSB, -1, 0),
                    Op(AVIF_SAMPLE_TRANSFORM_MSB, 61, 5),
                    Op(AVIF_SAMPLE_TRANSFORM_MSB,
                       std::numeric_limits<int32_t>::max(), 30),
                    Op(2, AVIF_SAMPLE_TRANSFORM_POW, 4, 16),
                    Op(4, AVIF_SAMPLE_TRANSFORM_POW, 2, 16),
                    Op(123, AVIF_SAMPLE_TRANSFORM_POW, 123, 255),
                    Op(123, AVIF_SAMPLE_TRANSFORM_MIN, 124, 123),
                    Op(123, AVIF_SAMPLE_TRANSFORM_MAX, 124, 124)));

//------------------------------------------------------------------------------

}  // namespace
}  // namespace avif
