/*
 *  Copyright (c) 2014 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/cropping_window_capturer.h"
#include "modules/desktop_capture/desktop_capturer_differ_wrapper.h"
#include "modules/desktop_capture/win/screen_capture_utils.h"
#include "modules/desktop_capture/win/selected_window_context.h"
#include "modules/desktop_capture/win/window_capture_utils.h"
#include "rtc_base/logging.h"
#include "rtc_base/trace_event.h"
#include "rtc_base/win/windows_version.h"

namespace webrtc {

namespace {

// Used to pass input data for verifying the selected window is on top.
struct TopWindowVerifierContext : public SelectedWindowContext {
  TopWindowVerifierContext(HWND selected_window,
                           HWND excluded_window,
                           DesktopRect selected_window_rect,
                           WindowCaptureHelperWin* window_capture_helper)
      : SelectedWindowContext(selected_window,
                              selected_window_rect,
                              window_capture_helper),
        excluded_window(excluded_window) {
    RTC_DCHECK_NE(selected_window, excluded_window);
  }

  // Determines whether the selected window is on top (not occluded by any
  // windows except for those it owns or any excluded window).
  bool IsTopWindow() {
    if (!IsSelectedWindowValid()) {
      return false;
    }

    // Enumerate all top-level windows above the selected window in Z-order,
    // checking whether any overlaps it. This uses FindWindowEx rather than
    // EnumWindows because the latter excludes certain system windows (e.g. the
    // Start menu & other taskbar menus) that should be detected here to avoid
    // inadvertent capture.
    int num_retries = 0;
    while (true) {
      HWND hwnd = nullptr;
      while ((hwnd = FindWindowEx(nullptr, hwnd, nullptr, nullptr))) {
        if (hwnd == selected_window()) {
          // Windows are enumerated in top-down Z-order, so we can stop
          // enumerating upon reaching the selected window & report it's on top.
          return true;
        }

        // Ignore the excluded window.
        if (hwnd == excluded_window) {
          continue;
        }

        // Ignore windows that aren't visible on the current desktop.
        if (!window_capture_helper()->IsWindowVisibleOnCurrentDesktop(hwnd)) {
          continue;
        }

        // Ignore Chrome notification windows, especially the notification for
        // the ongoing window sharing. Notes:
        // - This only works with notifications from Chrome, not other Apps.
        // - All notifications from Chrome will be ignored.
        // - This may cause part or whole of notification window being cropped
        // into the capturing of the target window if there is overlapping.
        if (window_capture_helper()->IsWindowChromeNotification(hwnd)) {
          continue;
        }

        // Ignore windows owned by the selected window since we want to capture
        // them.
        if (IsWindowOwnedBySelectedWindow(hwnd)) {
          continue;
        }

        // Check whether this window intersects with the selected window.
        if (IsWindowOverlappingSelectedWindow(hwnd)) {
          // If intersection is not empty, the selected window is not on top.
          return false;
        }
      }

      DWORD lastError = GetLastError();
      if (lastError == ERROR_SUCCESS) {
        // The enumeration completed successfully without finding the selected
        // window (which may have been closed).
        RTC_LOG(LS_WARNING) << "Failed to find selected window (only expected "
                               "if it was closed)";
        RTC_DCHECK(!IsWindow(selected_window()));
        return false;
      } else if (lastError == ERROR_INVALID_WINDOW_HANDLE) {
        // This error may occur if a window is closed around the time it's
        // enumerated; retry the enumeration in this case up to 10 times
        // (this should be a rare race & unlikely to recur).
        if (++num_retries <= 10) {
          RTC_LOG(LS_WARNING) << "Enumeration failed due to race with a window "
                                 "closing; retrying - retry #"
                              << num_retries;
          continue;
        } else {
          RTC_LOG(LS_ERROR)
              << "Exhausted retry allowance around window enumeration failures "
                 "due to races with windows closing";
        }
      }

      // The enumeration failed with an unexpected error (or more repeats of
      // an infrequently-expected error than anticipated). After logging this &
      // firing an assert when enabled, report that the selected window isn't
      // topmost to avoid inadvertent capture of other windows.
      RTC_LOG(LS_ERROR) << "Failed to enumerate windows: " << lastError;
      RTC_NOTREACHED();
      return false;
    }
  }

  const HWND excluded_window;
};

class CroppingWindowCapturerWin : public CroppingWindowCapturer {
 public:
  explicit CroppingWindowCapturerWin(const DesktopCaptureOptions& options)
      : CroppingWindowCapturer(options),
        enumerate_current_process_windows_(
            options.enumerate_current_process_windows()),
        full_screen_window_detector_(options.full_screen_window_detector()) {}

  void CaptureFrame() override;

 private:
  bool ShouldUseScreenCapturer() override;
  DesktopRect GetWindowRectInVirtualScreen() override;

  // Returns either selected by user sourceId or sourceId provided by
  // FullScreenWindowDetector
  WindowId GetWindowToCapture() const;

  // The region from GetWindowRgn in the desktop coordinate if the region is
  // rectangular, or the rect from GetWindowRect if the region is not set.
  DesktopRect window_region_rect_;

  WindowCaptureHelperWin window_capture_helper_;

  bool enumerate_current_process_windows_;

  rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector_;
};

void CroppingWindowCapturerWin::CaptureFrame() {
  DesktopCapturer* win_capturer = window_capturer();
  if (win_capturer) {
    // Feed the actual list of windows into full screen window detector.
    if (full_screen_window_detector_) {
      full_screen_window_detector_->UpdateWindowListIfNeeded(
          selected_window(), [this](DesktopCapturer::SourceList* sources) {
            // Get the list of top level windows, including ones with empty
            // title. win_capturer_->GetSourceList can't be used here
            // cause it filters out the windows with empty titles and
            // it uses responsiveness check which could lead to performance
            // issues.
            SourceList result;
            int window_list_flags =
                enumerate_current_process_windows_
                    ? GetWindowListFlags::kNone
                    : GetWindowListFlags::kIgnoreCurrentProcessWindows;

            if (!webrtc::GetWindowList(window_list_flags, &result))
              return false;

            // Filter out windows not visible on current desktop
            auto it = std::remove_if(
                result.begin(), result.end(), [this](const auto& source) {
                  HWND hwnd = reinterpret_cast<HWND>(source.id);
                  return !window_capture_helper_
                              .IsWindowVisibleOnCurrentDesktop(hwnd);
                });
            result.erase(it, result.end());

            sources->swap(result);
            return true;
          });
    }
    win_capturer->SelectSource(GetWindowToCapture());
  }

  CroppingWindowCapturer::CaptureFrame();
}

bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
  if (rtc::rtc_win::GetVersion() < rtc::rtc_win::Version::VERSION_WIN8 &&
      window_capture_helper_.IsAeroEnabled()) {
    return false;
  }

  const HWND selected = reinterpret_cast<HWND>(GetWindowToCapture());
  // Check if the window is visible on current desktop.
  if (!window_capture_helper_.IsWindowVisibleOnCurrentDesktop(selected)) {
    return false;
  }

  // Check if the window is a translucent layered window.
  const LONG window_ex_style = GetWindowLong(selected, GWL_EXSTYLE);
  if (window_ex_style & WS_EX_LAYERED) {
    COLORREF color_ref_key = 0;
    BYTE alpha = 0;
    DWORD flags = 0;

    // GetLayeredWindowAttributes fails if the window was setup with
    // UpdateLayeredWindow. We have no way to know the opacity of the window in
    // that case. This happens for Stiky Note (crbug/412726).
    if (!GetLayeredWindowAttributes(selected, &color_ref_key, &alpha, &flags))
      return false;

    // UpdateLayeredWindow is the only way to set per-pixel alpha and will cause
    // the previous GetLayeredWindowAttributes to fail. So we only need to check
    // the window wide color key or alpha.
    if ((flags & LWA_COLORKEY) || ((flags & LWA_ALPHA) && (alpha < 255))) {
      return false;
    }
  }

  if (!GetWindowRect(selected, &window_region_rect_)) {
    return false;
  }

  DesktopRect content_rect;
  if (!GetWindowContentRect(selected, &content_rect)) {
    return false;
  }

  DesktopRect region_rect;
  // Get the window region and check if it is rectangular.
  const int region_type =
      GetWindowRegionTypeWithBoundary(selected, &region_rect);

  // Do not use the screen capturer if the region is empty or not rectangular.
  if (region_type == COMPLEXREGION || region_type == NULLREGION) {
    return false;
  }

  if (region_type == SIMPLEREGION) {
    // The `region_rect` returned from GetRgnBox() is always in window
    // coordinate.
    region_rect.Translate(window_region_rect_.left(),
                          window_region_rect_.top());
    // MSDN: The window region determines the area *within* the window where the
    // system permits drawing.
    // https://msdn.microsoft.com/en-us/library/windows/desktop/dd144950(v=vs.85).aspx.
    //
    // `region_rect` should always be inside of `window_region_rect_`. So after
    // the intersection, `window_region_rect_` == `region_rect`. If so, what's
    // the point of the intersecting operations? Why cannot we directly retrieve
    // `window_region_rect_` from GetWindowRegionTypeWithBoundary() function?
    // TODO(zijiehe): Figure out the purpose of these intersections.
    window_region_rect_.IntersectWith(region_rect);
    content_rect.IntersectWith(region_rect);
  }

  // Check if the client area is out of the screen area. When the window is
  // maximized, only its client area is visible in the screen, the border will
  // be hidden. So we are using `content_rect` here.
  if (!GetFullscreenRect().ContainsRect(content_rect)) {
    return false;
  }

  // Check if the window is occluded by any other window, excluding the child
  // windows, context menus, and `excluded_window_`.
  // `content_rect` is preferred, see the comments on
  // IsWindowIntersectWithSelectedWindow().
  TopWindowVerifierContext context(selected,
                                   reinterpret_cast<HWND>(excluded_window()),
                                   content_rect, &window_capture_helper_);
  return context.IsTopWindow();
}

DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() {
  TRACE_EVENT0("webrtc",
               "CroppingWindowCapturerWin::GetWindowRectInVirtualScreen");
  DesktopRect window_rect;
  HWND hwnd = reinterpret_cast<HWND>(GetWindowToCapture());
  if (!GetCroppedWindowRect(hwnd, /*avoid_cropping_border*/ false, &window_rect,
                            /*original_rect*/ nullptr)) {
    RTC_LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
    return window_rect;
  }
  window_rect.IntersectWith(window_region_rect_);

  // Convert `window_rect` to be relative to the top-left of the virtual screen.
  DesktopRect screen_rect(GetFullscreenRect());
  window_rect.IntersectWith(screen_rect);
  window_rect.Translate(-screen_rect.left(), -screen_rect.top());
  return window_rect;
}

WindowId CroppingWindowCapturerWin::GetWindowToCapture() const {
  const auto selected_source = selected_window();
  const auto full_screen_source =
      full_screen_window_detector_
          ? full_screen_window_detector_->FindFullScreenWindow(selected_source)
          : 0;
  return full_screen_source ? full_screen_source : selected_source;
}

}  // namespace

// static
std::unique_ptr<DesktopCapturer> CroppingWindowCapturer::CreateCapturer(
    const DesktopCaptureOptions& options) {
  std::unique_ptr<DesktopCapturer> capturer(
      new CroppingWindowCapturerWin(options));
  if (capturer && options.detect_updated_region()) {
    capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer)));
  }

  return capturer;
}

}  // namespace webrtc
