/*
 *  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 <cmath>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <utility>

#include "rtc_base/checks.h"

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

namespace webrtc {

namespace {

bool ToUtf8(const CFStringRef str16, std::string* str8) {
  size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
                                                    kCFStringEncodingUTF8) +
                  1;
  std::unique_ptr<char[]> buffer(new char[maxlen]);
  if (!buffer ||
      !CFStringGetCString(str16, buffer.get(), maxlen, kCFStringEncodingUTF8)) {
    return false;
  }
  str8->assign(buffer.get());
  return true;
}

// 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;
}

}  // namespace

bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
                   bool ignore_minimized,
                   bool only_zero_layer) {
  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 = 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;
    }

    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 (only_zero_layer && layer != 0) {
      continue;
    }

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

    // If window title is empty, only consider it if it is either on screen or
    // fullscreen.
    CFStringRef window_title = reinterpret_cast<CFStringRef>(
        CFDictionaryGetValue(window, kCGWindowName));
    if (!window_title && !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,
                   bool only_zero_layer) {
  // Use a std::list so that iterators are preversed upon insertion and
  // deletion.
  std::list<DesktopCapturer::Source> sources;
  std::map<int, std::list<DesktopCapturer::Source>::const_iterator> pid_itr_map;
  const bool ret = GetWindowList(
      [&sources, &pid_itr_map](CFDictionaryRef window) {
        WindowId window_id = GetWindowId(window);
        if (window_id != kNullWindowId) {
          const std::string title = GetWindowTitle(window);
          const int pid = GetWindowOwnerPid(window);
          // Check if window for the same pid have been already inserted.
          std::map<int,
                   std::list<DesktopCapturer::Source>::const_iterator>::iterator
              itr = pid_itr_map.find(pid);

          // Only consider empty titles if the app has no other window with a
          // proper title.
          if (title.empty()) {
            std::string owner_name = GetWindowOwnerName(window);

            // At this time we do not know if there will be other windows
            // for the same pid unless they have been already inserted, hence
            // the check in the map. Also skip the window if owner name is
            // empty too.
            if (!owner_name.empty() && (itr == pid_itr_map.end())) {
              sources.push_back(DesktopCapturer::Source{window_id, owner_name});
              RTC_DCHECK(!sources.empty());
              // Get an iterator on the last valid element in the source list.
              std::list<DesktopCapturer::Source>::const_iterator last_source =
                  --sources.end();
              pid_itr_map.insert(
                  std::pair<int,
                            std::list<DesktopCapturer::Source>::const_iterator>(
                      pid, last_source));
            }
          } else {
            sources.push_back(DesktopCapturer::Source{window_id, title});
            // Once the window with empty title has been removed no other empty
            // windows are allowed for the same pid.
            if (itr != pid_itr_map.end() && (itr->second != sources.end())) {
              sources.erase(itr->second);
              // sdt::list::end() never changes during the lifetime of that
              // list.
              itr->second = sources.end();
            }
          }
        }
        return true;
      },
      ignore_minimized, only_zero_layer);

  if (!ret)
    return false;

  RTC_DCHECK(windows);
  windows->reserve(windows->size() + sources.size());
  std::copy(std::begin(sources), std::end(sources),
            std::back_inserter(*windows));

  return true;
}

// 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 IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
                        CGWindowID id) {
  bool fullscreen = false;
  GetWindowRef(id, [&](CFDictionaryRef window) {
    fullscreen = IsWindowFullScreen(desktop_config, window);
  });
  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 && ToUtf8(title, &result)) {
    return result;
  }

  return std::string();
}

std::string GetWindowTitle(CGWindowID id) {
  std::string title;
  if (GetWindowRef(id, [&title](CFDictionaryRef window) {
        title = GetWindowTitle(window);
      })) {
    return title;
  }
  return std::string();
}

std::string GetWindowOwnerName(CFDictionaryRef window) {
  CFStringRef owner_name = reinterpret_cast<CFStringRef>(
      CFDictionaryGetValue(window, kCGWindowOwnerName));
  std::string result;
  if (owner_name && ToUtf8(owner_name, &result)) {
    return result;
  }
  return std::string();
}

std::string GetWindowOwnerName(CGWindowID id) {
  std::string owner_name;
  if (GetWindowRef(id, [&owner_name](CFDictionaryRef window) {
        owner_name = GetWindowOwnerPid(window);
      })) {
    return owner_name;
  }
  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;
}

int GetWindowOwnerPid(CFDictionaryRef window) {
  CFNumberRef window_pid = reinterpret_cast<CFNumberRef>(
      CFDictionaryGetValue(window, kCGWindowOwnerPID));
  if (!window_pid) {
    return 0;
  }

  int pid;
  if (!CFNumberGetValue(window_pid, kCFNumberIntType, &pid)) {
    return 0;
  }

  return pid;
}

int GetWindowOwnerPid(CGWindowID id) {
  int pid;
  if (GetWindowRef(id, [&pid](CFDictionaryRef window) {
        pid = GetWindowOwnerPid(window);
      })) {
    return pid;
  }
  return 0;
}

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;
}

float GetWindowScaleFactor(CGWindowID id, DesktopSize size) {
  DesktopRect window_bounds = GetWindowBounds(id);
  float scale = 1.0f;

  if (!window_bounds.is_empty() && !size.is_empty()) {
    float scale_x = size.width() / window_bounds.width();
    float scale_y = size.height() / window_bounds.height();
    // Currently the scale in X and Y directions must be same.
    if ((std::fabs(scale_x - scale_y) <=
         std::numeric_limits<float>::epsilon() * std::max(scale_x, scale_y)) &&
        scale_x > 0.0f) {
      scale = scale_x;
    }
  }

  return scale;
}

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(CGWindowID id) {
  DesktopRect result;
  if (GetWindowRef(id, [&result](CFDictionaryRef window) {
        result = GetWindowBounds(window);
      })) {
    return result;
  }
  return DesktopRect();
}

}  // namespace webrtc
