/*
 *  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/mac/window_list_utils.h"

#include <ApplicationServices/ApplicationServices.h>

#include <algorithm>
#include <iterator>

#include "rtc_base/checks.h"
#include "rtc_base/macutils.h"

static_assert(
    static_cast<webrtc::WindowId>(kCGNullWindowID) == webrtc::kNullWindowId,
    "kNullWindowId needs to equal to kCGNullWindowID.");

namespace webrtc {

namespace {

// Get CFDictionaryRef from |id| and call |on_window| against it. This function
// returns false if native APIs fail, typically it indicates that the |id| does
// not represent a window. |on_window| will not be called if false is returned
// from this function.
bool GetWindowRef(CGWindowID id,
                  rtc::FunctionView<void(CFDictionaryRef)> on_window) {
  RTC_DCHECK(on_window);

  // TODO(zijiehe): |id| is a 32-bit integer, casting it to an array seems not
  // safe enough. Maybe we should create a new
  // const void* arr[] = {
  //   reinterpret_cast<void*>(id) }
  // };
  CFArrayRef window_id_array =
      CFArrayCreate(NULL, reinterpret_cast<const void**>(&id), 1, NULL);
  CFArrayRef window_array =
      CGWindowListCreateDescriptionFromArray(window_id_array);

  bool result = false;
  // TODO(zijiehe): CFArrayGetCount(window_array) should always return 1.
  // Otherwise, we should treat it as failure.
  if (window_array && CFArrayGetCount(window_array)) {
    on_window(reinterpret_cast<CFDictionaryRef>(
        CFArrayGetValueAtIndex(window_array, 0)));
    result = true;
  }

  if (window_array) {
    CFRelease(window_array);
  }
  CFRelease(window_id_array);
  return result;
}

// Scales the |rect| according to the DIP to physical pixel scale of |rect|.
// |rect| is in unscaled system coordinate, i.e. it's device-independent and the
// primary monitor starts from (0, 0). If |rect| overlaps multiple monitors, the
// returned size may not be accurate when monitors have different DIP settings.
// If |rect| is entirely out of the display, this function returns |rect|.
DesktopRect ApplyScaleFactorOfRect(
    const MacDesktopConfiguration& desktop_config,
    DesktopRect rect) {
  // TODO(http://crbug.com/778049): How does Mac OSX decide the scale factor
  // if one window is across two monitors with different DPIs.
  float scales[] = {
      GetScaleFactorAtPosition(desktop_config, rect.top_left()),
      GetScaleFactorAtPosition(desktop_config,
          DesktopVector(rect.left() + rect.width() / 2,
                        rect.top() + rect.height() / 2)),
      GetScaleFactorAtPosition(
            desktop_config, DesktopVector(rect.right(), rect.bottom())),
  };
  // Since GetScaleFactorAtPosition() returns 1 if the position is out of the
  // display, we always prefer a value which not equals to 1.
  float scale = *std::max_element(std::begin(scales), std::end(scales));
  if (scale == 1) {
    scale = *std::min_element(std::begin(scales), std::end(scales));
  }

  return DesktopRect::MakeXYWH(rect.left() * scale,
                               rect.top() * scale,
                               rect.width() * scale,
                               rect.height() * scale);
}

}  // namespace

bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
                   bool ignore_minimized) {
  RTC_DCHECK(on_window);

  // Only get on screen, non-desktop windows.
  // According to
  // https://developer.apple.com/documentation/coregraphics/cgwindowlistoption/1454105-optiononscreenonly ,
  // when kCGWindowListOptionOnScreenOnly is used, the order of windows are in
  // decreasing z-order.
  CFArrayRef window_array = CGWindowListCopyWindowInfo(
      kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
      kCGNullWindowID);
  if (!window_array)
    return false;

  MacDesktopConfiguration desktop_config;
  if (ignore_minimized) {
    desktop_config = MacDesktopConfiguration::GetCurrent(
        MacDesktopConfiguration::TopLeftOrigin);
  }

  // Check windows to make sure they have an id, title, and use window layer
  // other than 0.
  CFIndex count = CFArrayGetCount(window_array);
  for (CFIndex i = 0; i < count; i++) {
    CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
        CFArrayGetValueAtIndex(window_array, i));
    if (!window) {
      continue;
    }

    CFStringRef window_title = reinterpret_cast<CFStringRef>(
        CFDictionaryGetValue(window, kCGWindowName));
    if (!window_title) {
      continue;
    }

    CFNumberRef window_id = reinterpret_cast<CFNumberRef>(
        CFDictionaryGetValue(window, kCGWindowNumber));
    if (!window_id) {
      continue;
    }

    CFNumberRef window_layer = reinterpret_cast<CFNumberRef>(
        CFDictionaryGetValue(window, kCGWindowLayer));
    if (!window_layer) {
      continue;
    }

    // Skip windows with layer!=0 (menu, dock).
    int layer;
    if (!CFNumberGetValue(window_layer, kCFNumberIntType, &layer)) {
      continue;
    }
    if (layer != 0) {
      continue;
    }

    // Skip windows that are minimized and not full screen.
    if (ignore_minimized && !IsWindowOnScreen(window) &&
        !IsWindowFullScreen(desktop_config, window)) {
      continue;
    }

    if (!on_window(window)) {
      break;
    }
  }

  CFRelease(window_array);
  return true;
}

bool GetWindowList(DesktopCapturer::SourceList* windows,
                   bool ignore_minimized) {
  return GetWindowList(
      [windows](CFDictionaryRef window) {
        WindowId id = GetWindowId(window);
        std::string title = GetWindowTitle(window);
        if (id != kNullWindowId && !title.empty()) {
          windows->push_back(DesktopCapturer::Source{ id, title });
        }
        return true;
      },
      ignore_minimized);
}

// Returns true if the window is occupying a full screen.
bool IsWindowFullScreen(
    const MacDesktopConfiguration& desktop_config,
    CFDictionaryRef window) {
  bool fullscreen = false;
  CFDictionaryRef bounds_ref = reinterpret_cast<CFDictionaryRef>(
      CFDictionaryGetValue(window, kCGWindowBounds));

  CGRect bounds;
  if (bounds_ref &&
      CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds)) {
    for (MacDisplayConfigurations::const_iterator it =
             desktop_config.displays.begin();
         it != desktop_config.displays.end(); it++) {
      if (it->bounds.equals(DesktopRect::MakeXYWH(bounds.origin.x,
                                                  bounds.origin.y,
                                                  bounds.size.width,
                                                  bounds.size.height))) {
        fullscreen = true;
        break;
      }
    }
  }

  return fullscreen;
}

bool IsWindowOnScreen(CFDictionaryRef window) {
  CFBooleanRef on_screen = reinterpret_cast<CFBooleanRef>(
      CFDictionaryGetValue(window, kCGWindowIsOnscreen));
  return on_screen != NULL && CFBooleanGetValue(on_screen);
}

bool IsWindowOnScreen(CGWindowID id) {
  bool on_screen;
  if (GetWindowRef(id,
                   [&on_screen](CFDictionaryRef window) {
                     on_screen = IsWindowOnScreen(window);
                   })) {
    return on_screen;
  }
  return false;
}

std::string GetWindowTitle(CFDictionaryRef window) {
  CFStringRef title = reinterpret_cast<CFStringRef>(
      CFDictionaryGetValue(window, kCGWindowName));
  std::string result;
  if (title && rtc::ToUtf8(title, &result)) {
    return result;
  }
  return std::string();
}

WindowId GetWindowId(CFDictionaryRef window) {
  CFNumberRef window_id = reinterpret_cast<CFNumberRef>(
      CFDictionaryGetValue(window, kCGWindowNumber));
  if (!window_id) {
    return kNullWindowId;
  }

  // Note: WindowId is 64-bit on 64-bit system, but CGWindowID is always 32-bit.
  // CFNumberGetValue() fills only top 32 bits, so we should use CGWindowID to
  // receive the window id.
  CGWindowID id;
  if (!CFNumberGetValue(window_id, kCFNumberIntType, &id)) {
    return kNullWindowId;
  }

  return id;
}

float GetScaleFactorAtPosition(const MacDesktopConfiguration& desktop_config,
                               DesktopVector position) {
  // Find the dpi to physical pixel scale for the screen where the mouse cursor
  // is.
  for (auto it = desktop_config.displays.begin();
       it != desktop_config.displays.end(); ++it) {
    if (it->bounds.Contains(position)) {
      return it->dip_to_pixel_scale;
    }
  }
  return 1;
}

DesktopRect GetWindowBounds(CFDictionaryRef window) {
  CFDictionaryRef window_bounds = reinterpret_cast<CFDictionaryRef>(
      CFDictionaryGetValue(window, kCGWindowBounds));
  if (!window_bounds) {
    return DesktopRect();
  }

  CGRect gc_window_rect;
  if (!CGRectMakeWithDictionaryRepresentation(window_bounds, &gc_window_rect)) {
    return DesktopRect();
  }

  return DesktopRect::MakeXYWH(gc_window_rect.origin.x,
                               gc_window_rect.origin.y,
                               gc_window_rect.size.width,
                               gc_window_rect.size.height);
}

DesktopRect GetWindowBounds(const MacDesktopConfiguration& desktop_config,
                            CFDictionaryRef window) {
  DesktopRect rect = GetWindowBounds(window);
  return ApplyScaleFactorOfRect(desktop_config, rect);
}

DesktopRect GetWindowBounds(CGWindowID id) {
  DesktopRect result;
  if (GetWindowRef(id,
                   [&result](CFDictionaryRef window) {
                     result = GetWindowBounds(window);
                   })) {
    return result;
  }
  return DesktopRect();
}

DesktopRect GetWindowBounds(const MacDesktopConfiguration& desktop_config,
                            CGWindowID id) {
  DesktopRect rect = GetWindowBounds(id);
  return ApplyScaleFactorOfRect(desktop_config, rect);
}

}  // namespace webrtc
