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

#include "src/graphics/display/lib/api-protocols/cpp/display-engine-interface.h"

#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <lib/fit/function.h>
#include <lib/stdcompat/span.h>
#include <lib/zx/result.h>
#include <zircon/compiler.h>

#include <cstddef>
#include <cstdint>
#include <mutex>
#include <type_traits>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/graphics/display/lib/api-protocols/cpp/display-engine-interface.h"
#include "src/graphics/display/lib/api-types/cpp/config-check-result.h"
#include "src/graphics/display/lib/api-types/cpp/display-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-buffer-collection-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-capture-image-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-config-stamp.h"
#include "src/graphics/display/lib/api-types/cpp/driver-image-id.h"
#include "src/graphics/display/lib/api-types/cpp/driver-layer.h"
#include "src/graphics/display/lib/api-types/cpp/engine-info.h"
#include "src/graphics/display/lib/api-types/cpp/image-buffer-usage.h"
#include "src/graphics/display/lib/api-types/cpp/image-metadata.h"
#include "src/graphics/display/lib/api-types/cpp/mode-id.h"

namespace display {

namespace {

static_assert(!std::is_copy_constructible_v<DisplayEngineInterface>);
static_assert(!std::is_move_constructible_v<DisplayEngineInterface>);

static_assert(!std::is_final_v<DisplayEngineInterface>);
static_assert(std::is_polymorphic_v<DisplayEngineInterface>);

// Minimally functional strict mock for testing the default method
// implementations in `DisplayEngineInterface`.
class DisplayEngineMinimalMock final : public display::DisplayEngineInterface {
 public:
  using CheckConfigurationChecker = fit::function<display::ConfigCheckResult(
      display::DisplayId display_id, display::ModeId display_mode_id,
      cpp20::span<const display::DriverLayer> layers)>;
  using ApplyConfigurationChecker = fit::function<void(
      display::DisplayId display_id, display::ModeId display_mode_id,
      cpp20::span<const display::DriverLayer> layers, display::DriverConfigStamp config_stamp)>;

  DisplayEngineMinimalMock();
  DisplayEngineMinimalMock(const DisplayEngineMinimalMock&) = delete;
  DisplayEngineMinimalMock& operator=(const DisplayEngineMinimalMock&) = delete;
  ~DisplayEngineMinimalMock();

  void ExpectCheckConfiguration(CheckConfigurationChecker checker);
  void ExpectApplyConfiguration(ApplyConfigurationChecker checker);

  // Must be called at least once during an instance's lifetime.
  //
  // Tests are recommended to call this in a TearDown() method, or at the end of
  // the test case implementation.
  void CheckAllCallsReplayed();

  // `display::DisplayEngineInterface`:
  EngineInfo CompleteCoordinatorConnection() override;
  zx::result<> ImportBufferCollection(
      display::DriverBufferCollectionId buffer_collection_id,
      fidl::ClientEnd<fuchsia_sysmem2::BufferCollectionToken> buffer_collection_token) override;
  zx::result<> ReleaseBufferCollection(
      display::DriverBufferCollectionId buffer_collection_id) override;
  zx::result<display::DriverImageId> ImportImage(
      const display::ImageMetadata& image_metadata,
      display::DriverBufferCollectionId buffer_collection_id, uint32_t buffer_index) override;
  zx::result<display::DriverCaptureImageId> ImportImageForCapture(
      display::DriverBufferCollectionId buffer_collection_id, uint32_t buffer_index) override;
  void ReleaseImage(display::DriverImageId driver_image_id) override;
  display::ConfigCheckResult CheckConfiguration(
      display::DisplayId display_id, display::ModeId display_mode_id,
      cpp20::span<const display::DriverLayer> layers) override;
  void ApplyConfiguration(display::DisplayId display_id, display::ModeId display_mode_id,
                          cpp20::span<const display::DriverLayer> layers,
                          display::DriverConfigStamp driver_config_stamp) override;
  zx::result<> SetBufferCollectionConstraints(
      const display::ImageBufferUsage& image_buffer_usage,
      display::DriverBufferCollectionId buffer_collection_id) override;

 private:
  struct Expectation {
    CheckConfigurationChecker check_configuration_checker;
    ApplyConfigurationChecker apply_configuration_checker;
  };

  std::mutex mutex_;
  std::vector<Expectation> expectations_ __TA_GUARDED(mutex_);
  size_t call_index_ __TA_GUARDED(mutex_) = 0;
  bool check_all_calls_replayed_called_ __TA_GUARDED(mutex_) = false;
};

DisplayEngineMinimalMock::DisplayEngineMinimalMock() = default;

DisplayEngineMinimalMock::~DisplayEngineMinimalMock() {
  ZX_ASSERT_MSG(check_all_calls_replayed_called_, "CheckAllCallsReplayed() not called on a mock");
}

void DisplayEngineMinimalMock::ExpectCheckConfiguration(CheckConfigurationChecker checker) {
  std::lock_guard<std::mutex> lock(mutex_);
  expectations_.push_back({.check_configuration_checker = std::move(checker)});
}

void DisplayEngineMinimalMock::ExpectApplyConfiguration(ApplyConfigurationChecker checker) {
  std::lock_guard<std::mutex> lock(mutex_);
  expectations_.push_back({.apply_configuration_checker = std::move(checker)});
}

void DisplayEngineMinimalMock::CheckAllCallsReplayed() {
  std::lock_guard<std::mutex> lock(mutex_);
  ZX_ASSERT_MSG(expectations_.size() == call_index_, "%zu expected calls were not received",
                expectations_.size() - call_index_);
  check_all_calls_replayed_called_ = true;
}

EngineInfo DisplayEngineMinimalMock::CompleteCoordinatorConnection() {
  ZX_PANIC("Received unexpected call type");
  return display::EngineInfo{{}};
}

zx::result<> DisplayEngineMinimalMock::ImportBufferCollection(
    display::DriverBufferCollectionId buffer_collection_id,
    fidl::ClientEnd<fuchsia_sysmem2::BufferCollectionToken> buffer_collection_token) {
  ZX_PANIC("Received unexpected call type");
  return zx::error(ZX_ERR_NOT_SUPPORTED);
}

zx::result<> DisplayEngineMinimalMock::ReleaseBufferCollection(
    display::DriverBufferCollectionId buffer_collection_id) {
  ZX_PANIC("Received unexpected call type");
  return zx::error(ZX_ERR_NOT_SUPPORTED);
}

zx::result<display::DriverImageId> DisplayEngineMinimalMock::ImportImage(
    const display::ImageMetadata& image_metadata,
    display::DriverBufferCollectionId buffer_collection_id, uint32_t buffer_index) {
  ZX_PANIC("Received unexpected call type");
  return zx::error(ZX_ERR_NOT_SUPPORTED);
}

zx::result<display::DriverCaptureImageId> DisplayEngineMinimalMock::ImportImageForCapture(
    display::DriverBufferCollectionId buffer_collection_id, uint32_t buffer_index) {
  ZX_PANIC("Received unexpected call type");
  return zx::error(ZX_ERR_NOT_SUPPORTED);
}

void DisplayEngineMinimalMock::ReleaseImage(display::DriverImageId driver_image_id) {
  ZX_PANIC("Received unexpected call type");
}

display::ConfigCheckResult DisplayEngineMinimalMock::CheckConfiguration(
    display::DisplayId display_id, display::ModeId display_mode_id,
    cpp20::span<const display::DriverLayer> layers) {
  std::lock_guard<std::mutex> lock(mutex_);
  ZX_ASSERT_MSG(call_index_ < expectations_.size(), "All expected calls were already received");
  Expectation& call_expectation = expectations_[call_index_];
  ++call_index_;

  ZX_ASSERT_MSG(call_expectation.check_configuration_checker != nullptr,
                "Received call type does not match expected call type");
  return call_expectation.check_configuration_checker(display_id, display_mode_id, layers);
}

void DisplayEngineMinimalMock::ApplyConfiguration(display::DisplayId display_id,
                                                  display::ModeId display_mode_id,
                                                  cpp20::span<const display::DriverLayer> layers,
                                                  display::DriverConfigStamp driver_config_stamp) {
  std::lock_guard<std::mutex> lock(mutex_);
  ZX_ASSERT_MSG(call_index_ < expectations_.size(), "All expected calls were already received");
  Expectation& call_expectation = expectations_[call_index_];
  ++call_index_;

  ZX_ASSERT_MSG(call_expectation.apply_configuration_checker != nullptr,
                "Received call type does not match expected call type");
  call_expectation.apply_configuration_checker(display_id, display_mode_id, layers,
                                               driver_config_stamp);
}

zx::result<> DisplayEngineMinimalMock::SetBufferCollectionConstraints(
    const display::ImageBufferUsage& image_buffer_usage,
    display::DriverBufferCollectionId buffer_collection_id) {
  ZX_PANIC("Received unexpected call type");
  return zx::error(ZX_ERR_NOT_SUPPORTED);
}

class DisplayEngineInterfaceTest : public ::testing::Test {
 public:
  void TearDown() override { mock_display_engine_.CheckAllCallsReplayed(); }

 protected:
  DisplayEngineMinimalMock mock_display_engine_;
};

// Valid layer with properties aimed at testing API translation layers.
//
// The returned layer's properties are all different numbers. This is intended to
// help catch logic errors in API translation layers, such as swapping dimensions
// (width vs height) or size and position.
//
// `seed` is a small integer that results in small variations in the layer
// properties. This is intended to help catch logic errors in accessing and
// converting layers stored in arrays.
constexpr display::DriverLayer CreateValidLayerWithSeed(int seed) {
  const uint8_t color_blue = 0x40 + static_cast<uint8_t>(seed % 16);
  const uint8_t color_green = 0x50 + static_cast<uint8_t>((seed / 16) % 16);
  const uint8_t color_red = 0x60 + static_cast<uint8_t>(seed % 16);
  const uint8_t color_alpha = 0x70 + static_cast<uint8_t>((seed / 16) % 16);

  return display::DriverLayer({
      .display_destination = display::Rectangle(
          {.x = 100 + seed, .y = 200 + seed, .width = 300 + seed, .height = 400 + seed}),
      .image_source = display::Rectangle(
          {.x = 500 + seed, .y = 600 + seed, .width = 700 + seed, .height = 800 + seed}),
      .image_id = display::DriverImageId(8000 + seed),
      .image_metadata = display::ImageMetadata({.width = 2000 + seed,
                                                .height = 1000 + seed,
                                                .tiling_type = display::ImageTilingType::kLinear}),
      .fallback_color = display::Color(
          {.format = display::PixelFormat::kB8G8R8A8,
           .bytes = std::initializer_list<uint8_t>{color_blue, color_green, color_red, color_alpha,
                                                   0, 0, 0, 0}}),
      .image_source_transformation = display::CoordinateTransformation::kIdentity,
  });
}

TEST_F(DisplayEngineInterfaceTest, CheckConfigurationIdentityColorConversionSuccess) {
  static constexpr display::DisplayId kDisplayId(1);
  static constexpr display::ModeId kModeId(2);
  static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};

  mock_display_engine_.ExpectCheckConfiguration(
      [&](display::DisplayId display_id, display::ModeId mode_id,
          cpp20::span<const display::DriverLayer> layers) {
        EXPECT_EQ(kDisplayId, display_id);
        EXPECT_EQ(kModeId, mode_id);
        EXPECT_THAT(layers, ::testing::ElementsAreArray(kLayers));
        return display::ConfigCheckResult::kOk;
      });

  DisplayEngineInterface& display_engine = mock_display_engine_;
  EXPECT_EQ(display::ConfigCheckResult::kOk,
            display_engine.CheckConfiguration(kDisplayId, kModeId,
                                              display::ColorConversion::kIdentity, kLayers));
}

TEST_F(DisplayEngineInterfaceTest, CheckConfigurationNonIdentityColorConversionError) {
  static constexpr display::DisplayId kDisplayId(1);
  static constexpr display::ModeId kModeId(2);
  const display::ColorConversion kColorConversion = {
      {
          .preoffsets = {1.0f, 2.0f, 3.0f},
          .coefficients =
              {
                  std::array<float, 3>{4.0f, 5.0f, 6.0f},
                  std::array<float, 3>{7.0f, 8.0f, 9.0f},
                  std::array<float, 3>{10.0f, 11.0f, 12.0f},
              },
          .postoffsets = {13.0f, 14.0f, 15.0f},
      },
  };
  static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
  //
  // The mock is not expected to be called because the default
  // `CheckConfiguration()` implementation in `DisplayEngineInterface` will
  // return `kUnsupportedConfig` when the color conversion is not identity.

  DisplayEngineInterface& display_engine = mock_display_engine_;
  EXPECT_EQ(display::ConfigCheckResult::kUnsupportedConfig,
            display_engine.CheckConfiguration(kDisplayId, kModeId, kColorConversion, kLayers));
}

TEST_F(DisplayEngineInterfaceTest, ApplyConfigurationIdentityColorConversion) {
  static constexpr display::DisplayId kDisplayId(1);
  static constexpr display::ModeId kModeId(2);
  static constexpr std::array<display::DriverLayer, 1> kLayers = {CreateValidLayerWithSeed(0)};
  static constexpr display::DriverConfigStamp kConfigStamp(42);

  mock_display_engine_.ExpectApplyConfiguration(
      [&](display::DisplayId display_id, display::ModeId mode_id,
          cpp20::span<const display::DriverLayer> layers, display::DriverConfigStamp config_stamp) {
        EXPECT_EQ(kDisplayId, display_id);
        EXPECT_EQ(kModeId, mode_id);
        EXPECT_THAT(layers, ::testing::ElementsAreArray(kLayers));
        EXPECT_EQ(kConfigStamp, config_stamp);
      });

  DisplayEngineInterface& display_engine = mock_display_engine_;
  display_engine.ApplyConfiguration(kDisplayId, kModeId, display::ColorConversion::kIdentity,
                                    kLayers, kConfigStamp);
}

}  // namespace

}  // namespace display
