/*
 *  Copyright (c) 2013 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 <assert.h>
#include <ApplicationServices/ApplicationServices.h>
#include <Cocoa/Cocoa.h>
#include <CoreFoundation/CoreFoundation.h>

#include <utility>

#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/desktop_frame.h"
#include "modules/desktop_capture/mac/desktop_configuration.h"
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
#include "modules/desktop_capture/mac/window_list_utils.h"
#include "modules/desktop_capture/window_finder_mac.h"
#include "rtc_base/constructormagic.h"
#include "rtc_base/logging.h"
#include "rtc_base/macutils.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "rtc_base/trace_event.h"

namespace webrtc {

namespace {

// Returns true if the window exists.
bool IsWindowValid(CGWindowID id) {
  CFArrayRef window_id_array =
      CFArrayCreate(nullptr, reinterpret_cast<const void**>(&id), 1, nullptr);
  CFArrayRef window_array =
      CGWindowListCreateDescriptionFromArray(window_id_array);
  bool valid = window_array && CFArrayGetCount(window_array);
  CFRelease(window_id_array);
  CFRelease(window_array);

  return valid;
}

class WindowCapturerMac : public DesktopCapturer {
 public:
  explicit WindowCapturerMac(rtc::scoped_refptr<FullScreenChromeWindowDetector>
                                 full_screen_chrome_window_detector,
                             rtc::scoped_refptr<DesktopConfigurationMonitor>
                                 configuration_monitor);
  ~WindowCapturerMac() override;

  // DesktopCapturer interface.
  void Start(Callback* callback) override;
  void CaptureFrame() override;
  bool GetSourceList(SourceList* sources) override;
  bool SelectSource(SourceId id) override;
  bool FocusOnSelectedSource() override;
  bool IsOccluded(const DesktopVector& pos) override;

 private:
  Callback* callback_ = nullptr;

  // The window being captured.
  CGWindowID window_id_ = 0;

  const rtc::scoped_refptr<FullScreenChromeWindowDetector>
      full_screen_chrome_window_detector_;

  const rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;

  WindowFinderMac window_finder_;

  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerMac);
};

WindowCapturerMac::WindowCapturerMac(
    rtc::scoped_refptr<FullScreenChromeWindowDetector>
        full_screen_chrome_window_detector,
    rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor)
    : full_screen_chrome_window_detector_(
          std::move(full_screen_chrome_window_detector)),
      configuration_monitor_(std::move(configuration_monitor)),
      window_finder_(configuration_monitor_) {}

WindowCapturerMac::~WindowCapturerMac() {}

bool WindowCapturerMac::GetSourceList(SourceList* sources) {
  return webrtc::GetWindowList(sources, true);
}

bool WindowCapturerMac::SelectSource(SourceId id) {
  if (!IsWindowValid(id))
    return false;
  window_id_ = id;
  return true;
}

bool WindowCapturerMac::FocusOnSelectedSource() {
  if (!window_id_)
    return false;

  CGWindowID ids[1];
  ids[0] = window_id_;
  CFArrayRef window_id_array =
      CFArrayCreate(nullptr, reinterpret_cast<const void**>(&ids), 1, nullptr);

  CFArrayRef window_array =
      CGWindowListCreateDescriptionFromArray(window_id_array);
  if (!window_array || 0 == CFArrayGetCount(window_array)) {
    // Could not find the window. It might have been closed.
    RTC_LOG(LS_INFO) << "Window not found";
    CFRelease(window_id_array);
    return false;
  }

  CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
      CFArrayGetValueAtIndex(window_array, 0));
  CFNumberRef pid_ref = reinterpret_cast<CFNumberRef>(
      CFDictionaryGetValue(window, kCGWindowOwnerPID));

  int pid;
  CFNumberGetValue(pid_ref, kCFNumberIntType, &pid);

  // TODO(jiayl): this will bring the process main window to the front. We
  // should find a way to bring only the window to the front.
  bool result =
      [[NSRunningApplication runningApplicationWithProcessIdentifier: pid]
          activateWithOptions: NSApplicationActivateIgnoringOtherApps];

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

bool WindowCapturerMac::IsOccluded(const DesktopVector& pos) {
  DesktopVector sys_pos = pos;
  if (configuration_monitor_) {
    configuration_monitor_->Lock();
    auto configuration = configuration_monitor_->desktop_configuration();
    configuration_monitor_->Unlock();
    sys_pos = pos.add(configuration.bounds.top_left());
  }
  return window_finder_.GetWindowUnderPoint(sys_pos) != window_id_;
}

void WindowCapturerMac::Start(Callback* callback) {
  assert(!callback_);
  assert(callback);

  callback_ = callback;
}

void WindowCapturerMac::CaptureFrame() {
  TRACE_EVENT0("webrtc", "WindowCapturerMac::CaptureFrame");

  if (!IsWindowValid(window_id_)) {
    RTC_LOG(LS_ERROR) << "The window is not valid any longer.";
    callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
    return;
  }

  CGWindowID on_screen_window = window_id_;
  if (full_screen_chrome_window_detector_) {
    CGWindowID full_screen_window =
        full_screen_chrome_window_detector_->FindFullScreenWindow(window_id_);

    if (full_screen_window != kCGNullWindowID)
      on_screen_window = full_screen_window;
  }

  CGImageRef window_image = CGWindowListCreateImage(
      CGRectNull, kCGWindowListOptionIncludingWindow,
      on_screen_window, kCGWindowImageBoundsIgnoreFraming);

  if (!window_image) {
    RTC_LOG(LS_WARNING) << "Temporarily failed to capture window.";
    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
    return;
  }

  int bits_per_pixel = CGImageGetBitsPerPixel(window_image);
  if (bits_per_pixel != 32) {
    RTC_LOG(LS_ERROR) << "Unsupported window image depth: " << bits_per_pixel;
    CFRelease(window_image);
    callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
    return;
  }

  int width = CGImageGetWidth(window_image);
  int height = CGImageGetHeight(window_image);
  CGDataProviderRef provider = CGImageGetDataProvider(window_image);
  CFDataRef cf_data = CGDataProviderCopyData(provider);
  std::unique_ptr<DesktopFrame> frame(
      new BasicDesktopFrame(DesktopSize(width, height)));

  int src_stride = CGImageGetBytesPerRow(window_image);
  const uint8_t* src_data = CFDataGetBytePtr(cf_data);
  for (int y = 0; y < height; ++y) {
    memcpy(frame->data() + frame->stride() * y, src_data + src_stride * y,
           DesktopFrame::kBytesPerPixel * width);
  }

  CFRelease(cf_data);
  CFRelease(window_image);

  frame->mutable_updated_region()->SetRect(
      DesktopRect::MakeSize(frame->size()));
  frame->set_top_left(GetWindowBounds(on_screen_window).top_left());

  float scale_factor = GetWindowScaleFactor(window_id_, frame->size());
  frame->set_dpi(DesktopVector(kStandardDPI * scale_factor, kStandardDPI * scale_factor));

  callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));

  if (full_screen_chrome_window_detector_)
    full_screen_chrome_window_detector_->UpdateWindowListIfNeeded(window_id_);
}

}  // namespace

// static
std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
    const DesktopCaptureOptions& options) {
  return std::unique_ptr<DesktopCapturer>(
      new WindowCapturerMac(options.full_screen_chrome_window_detector(),
                            options.configuration_monitor()));
}

}  // namespace webrtc
