/*
 *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/desktop_capture/window_finder.h"

#include <cstdint>
#include <memory>

#include "api/scoped_refptr.h"
#include "modules/desktop_capture/desktop_capture_types.h"
#include "modules/desktop_capture/desktop_geometry.h"
#include "modules/desktop_capture/screen_drawer.h"
#include "rtc_base/logging.h"
#include "test/gtest.h"

#if defined(WEBRTC_USE_X11)
#include "modules/desktop_capture/linux/x11/shared_x_display.h"
#include "modules/desktop_capture/linux/x11/x_atom_cache.h"
#endif

#if defined(WEBRTC_WIN)
#include <windows.h>

#include "modules/desktop_capture/win/window_capture_utils.h"
#include "modules/desktop_capture/window_finder_win.h"
#endif

namespace webrtc {

namespace {

#if defined(WEBRTC_WIN)
// ScreenDrawerWin does not have a message loop, so it's unresponsive to user
// inputs. WindowFinderWin cannot detect this kind of unresponsive windows.
// Instead, console window is used to test WindowFinderWin.
// TODO(b/373792116): Reenable once flakiness is fixed.
TEST(WindowFinderTest, DISABLED_FindConsoleWindow) {
  // Creates a ScreenDrawer to avoid this test from conflicting with
  // ScreenCapturerIntegrationTest: both tests require its window to be in
  // foreground.
  //
  // In ScreenCapturer related tests, this is controlled by
  // ScreenDrawer, which has a global lock to ensure only one ScreenDrawer
  // window is active. So even we do not use ScreenDrawer for Windows test,
  // creating an instance can block ScreenCapturer related tests until this test
  // finishes.
  //
  // Usually the test framework should take care of this "isolated test"
  // requirement, but unfortunately WebRTC trybots do not support this.
  std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
  const int kMaxSize = 10000;
  // Enlarges current console window.
  system("mode 1000,1000");
  const HWND console_window = GetConsoleWindow();
  // Ensures that current console window is visible.
  ShowWindow(console_window, SW_MAXIMIZE);
  // Moves the window to the top-left of the display.
  if (!MoveWindow(console_window, 0, 0, kMaxSize, kMaxSize, true)) {
    FAIL() << "Failed to move window. Error code: " << GetLastError();
  }

  bool should_restore_notopmost =
      (GetWindowLong(console_window, GWL_EXSTYLE) & WS_EX_TOPMOST) == 0;

  // Brings console window to top.
  if (!SetWindowPos(console_window, HWND_TOPMOST, 0, 0, 0, 0,
                    SWP_NOMOVE | SWP_NOSIZE)) {
    FAIL() << "Failed to bring window to top. Error code: " << GetLastError();
  }
  if (!BringWindowToTop(console_window)) {
    FAIL() << "Failed second attempt to bring window to top. Error code: "
           << GetLastError();
  }

  bool success = false;
  WindowFinderWin finder;
  for (int i = 0; i < kMaxSize; i++) {
    const DesktopVector spot(i, i);
    const HWND id = reinterpret_cast<HWND>(finder.GetWindowUnderPoint(spot));

    if (id == console_window) {
      success = true;
      break;
    }
    RTC_LOG(LS_INFO) << "Expected window " << console_window
                     << ". Found window " << id;
  }
  if (should_restore_notopmost)
    SetWindowPos(console_window, HWND_NOTOPMOST, 0, 0, 0, 0,
                 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

  if (!success)
    FAIL();
}

#else
TEST(WindowFinderTest, FindDrawerWindow) {
  WindowFinder::Options options;
#if defined(WEBRTC_USE_X11)
  std::unique_ptr<XAtomCache> cache;
  const auto shared_x_display = SharedXDisplay::CreateDefault();
  if (shared_x_display) {
    cache = std::make_unique<XAtomCache>(shared_x_display->display());
    options.cache = cache.get();
  }
#endif
  std::unique_ptr<WindowFinder> finder = WindowFinder::Create(options);
  if (!finder) {
    RTC_LOG(LS_WARNING)
        << "No WindowFinder implementation for current platform.";
    return;
  }

  std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
  if (!drawer) {
    RTC_LOG(LS_WARNING)
        << "No ScreenDrawer implementation for current platform.";
    return;
  }

  if (drawer->window_id() == kNullWindowId) {
    // TODO(zijiehe): WindowFinderTest can use a dedicated window without
    // relying on ScreenDrawer.
    RTC_LOG(LS_WARNING)
        << "ScreenDrawer implementation for current platform does "
           "create a window.";
    return;
  }

  // ScreenDrawer may not be able to bring the window to the top. So we test
  // several spots, at least one of them should succeed.
  const DesktopRect region = drawer->DrawableRegion();
  if (region.is_empty()) {
    RTC_LOG(LS_WARNING)
        << "ScreenDrawer::DrawableRegion() is too small for the "
           "WindowFinderTest.";
    return;
  }

  for (int i = 0; i < region.width(); i++) {
    const DesktopVector spot(
        region.left() + i, region.top() + i * region.height() / region.width());
    const WindowId id = finder->GetWindowUnderPoint(spot);
    if (id == drawer->window_id()) {
      return;
    }
  }

  FAIL();
}
#endif

TEST(WindowFinderTest, ShouldReturnNullWindowIfSpotIsOutOfScreen) {
  WindowFinder::Options options;
#if defined(WEBRTC_USE_X11)
  std::unique_ptr<XAtomCache> cache;
  const auto shared_x_display = SharedXDisplay::CreateDefault();
  if (shared_x_display) {
    cache = std::make_unique<XAtomCache>(shared_x_display->display());
    options.cache = cache.get();
  }
#endif
  std::unique_ptr<WindowFinder> finder = WindowFinder::Create(options);
  if (!finder) {
    RTC_LOG(LS_WARNING)
        << "No WindowFinder implementation for current platform.";
    return;
  }

  ASSERT_EQ(kNullWindowId,
            finder->GetWindowUnderPoint(DesktopVector(INT16_MAX, INT16_MAX)));
  ASSERT_EQ(kNullWindowId,
            finder->GetWindowUnderPoint(DesktopVector(INT16_MAX, INT16_MIN)));
  ASSERT_EQ(kNullWindowId,
            finder->GetWindowUnderPoint(DesktopVector(INT16_MIN, INT16_MAX)));
  ASSERT_EQ(kNullWindowId,
            finder->GetWindowUnderPoint(DesktopVector(INT16_MIN, INT16_MIN)));
}

}  // namespace

}  // namespace webrtc
