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

#include "chrome/browser/android/compositor/compositor_view.h"

#include <memory>
#include <optional>

#include "base/android/jni_android.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/android/compositor/tab_content_manager.h"
#include "components/viz/common/frame_timing_details.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/android/resources/ui_resource_provider.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/presentation_feedback.h"

namespace android {

class MockCompositor : public content::Compositor {
 public:
  MockCompositor() = default;
  ~MockCompositor() override = default;

  MOCK_METHOD(void,
              SetRootWindow,
              (ui::WindowAndroid * window_android),
              (override));
  MOCK_METHOD(void,
              SetRootLayer,
              (scoped_refptr<cc::slim::Layer> root),
              (override));
  MOCK_METHOD(std::optional<int>,
              SetSurface,
              (const base::android::JavaRef<jobject>& surface,
               bool can_be_used_with_surface_control,
               const base::android::JavaRef<jobject>& browser_input_token),
              (override));
  MOCK_METHOD(void, SetWindowBounds, (const gfx::Size& size), (override));
  MOCK_METHOD(const gfx::Size&, GetWindowBounds, (), (override));
  MOCK_METHOD(void, SetRequiresAlphaChannel, (bool required), (override));
  MOCK_METHOD(void, SetNeedsComposite, (), (override));
  MOCK_METHOD(void, SetDrawPaused, (bool paused), (override));
  MOCK_METHOD(base::WeakPtr<ui::UIResourceProvider>,
              GetUIResourceProvider,
              (),
              (override));
  MOCK_METHOD(ui::ResourceManager&, GetResourceManager, (), (override));
  MOCK_METHOD(void, CacheBackBufferForCurrentSurface, (), (override));
  MOCK_METHOD(void, EvictCachedBackBuffer, (), (override));
  MOCK_METHOD(
      void,
      RequestSuccessfulPresentationTimeForNextFrame,
      (base::OnceCallback<void(const viz::FrameTimingDetails&)> callback),
      (override));
  MOCK_METHOD(
      void,
      RequestPresentationTimeForNextFrame,
      (base::OnceCallback<void(const gfx::PresentationFeedback&)> callback),
      (override));
  MOCK_METHOD(void, SetBackgroundColor, (int color), (override));
  MOCK_METHOD(void, PreserveChildSurfaceControls, (), (override));
  MOCK_METHOD(void,
              SetDidSwapBuffersCallbackEnabled,
              (bool enable),
              (override));
  MOCK_METHOD(void, OnViewAndroidAttached, (ui::ViewAndroid * view));
  MOCK_METHOD(void, OnViewAndroidDetached, (ui::ViewAndroid * view));
};

class FakeTabContentManager : public TabContentManager {
 public:
  explicit FakeTabContentManager(JNIEnv* env)
      : TabContentManager(env, nullptr, 0, 0, 0, false) {}
  ~FakeTabContentManager() override = default;
  void OnUIResourcesWereEvicted() {}
};

class CompositorViewTest : public ::testing::Test {
 public:
  CompositorViewTest() = default;

  void SetUp() override {
    JNIEnv* env = base::android::AttachCurrentThread();
    auto compositor = std::make_unique<MockCompositor>();
    compositor_ = compositor.get();
    tab_content_manager_ = std::make_unique<FakeTabContentManager>(env);
    compositor_view_ =
        new CompositorView(env, nullptr, /*window_android=*/nullptr,
                           tab_content_manager_.get(), std::move(compositor));
  }

  void TearDown() override {
    JNIEnv* env = base::android::AttachCurrentThread();
    compositor_view_->Destroy(env);
    compositor_view_ = nullptr;
  }

 protected:
  content::BrowserTaskEnvironment task_environment_{
      content::BrowserTaskEnvironment::MainThreadType::UI};
  std::unique_ptr<FakeTabContentManager> tab_content_manager_;
  raw_ptr<CompositorView> compositor_view_;
  raw_ptr<MockCompositor> compositor_;
};

TEST_F(CompositorViewTest, SetOverlayXrFullScreenMode) {
  JNIEnv* env = base::android::AttachCurrentThread();

  // Enable XR mode.
  EXPECT_CALL(*compositor_, SetBackgroundColor(SK_ColorTRANSPARENT));
  compositor_view_->SetOverlayXrFullScreenMode(env, true);

  // Calling again with true should do nothing.
  compositor_view_->SetOverlayXrFullScreenMode(env, true);

  // Disable XR mode.
  EXPECT_CALL(*compositor_, SetBackgroundColor(SK_ColorWHITE));
  compositor_view_->SetOverlayXrFullScreenMode(env, false);
}

}  // namespace android
