// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_CAPTURE_MACHINE_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_CAPTURE_MACHINE_H_

#include <memory>

#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/media/capture/cursor_renderer_aura.h"
#include "media/capture/content/screen_capture_device_core.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/base/cursor/cursors_aura.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_animation_observer.h"

namespace cc {
class CopyOutputResult;
}  // namespace cc

namespace device {
class PowerSaveBlocker;
}  // namespace device

namespace display_compositor {
class ReadbackYUVInterface;
}

namespace content {

class AuraWindowCaptureMachine
    : public media::VideoCaptureMachine,
      public aura::WindowObserver,
      public ui::CompositorAnimationObserver {
 public:
  AuraWindowCaptureMachine();
  ~AuraWindowCaptureMachine() override;

  // VideoCaptureMachine overrides.
  void Start(const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
             const media::VideoCaptureParams& params,
             const base::Callback<void(bool)> callback) override;
  void Suspend() override;
  void Resume() override;
  void Stop(const base::Closure& callback) override;
  void MaybeCaptureForRefresh() override;

  // Implements aura::WindowObserver.
  void OnWindowBoundsChanged(aura::Window* window,
                             const gfx::Rect& old_bounds,
                             const gfx::Rect& new_bounds) override;
  void OnWindowDestroying(aura::Window* window) override;
  void OnWindowAddedToRootWindow(aura::Window* window) override;
  void OnWindowRemovingFromRootWindow(aura::Window* window,
                                      aura::Window* new_root) override;

  // ui::CompositorAnimationObserver implementation.
  void OnAnimationStep(base::TimeTicks timestamp) override;
  void OnCompositingShuttingDown(ui::Compositor* compositor) override;

  // Sets the window to use for capture.
  void SetWindow(aura::Window* window);

 private:
  bool InternalStart(
      const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
      const media::VideoCaptureParams& params);
  void InternalSuspend();
  void InternalResume();
  void InternalStop(const base::Closure& callback);

  // Captures a frame. |event_time| is provided by the compositor, or is null
  // for refresh requests.
  void Capture(base::TimeTicks event_time);

  // Update capture size. Must be called on the UI thread.
  void UpdateCaptureSize();

  using CaptureFrameCallback =
      media::ThreadSafeCaptureOracle::CaptureFrameCallback;

  // Response callback for cc::Layer::RequestCopyOfOutput().
  void DidCopyOutput(scoped_refptr<media::VideoFrame> video_frame,
                     base::TimeTicks event_time,
                     base::TimeTicks start_time,
                     const CaptureFrameCallback& capture_frame_cb,
                     std::unique_ptr<cc::CopyOutputResult> result);

  // A helper which does the real work for DidCopyOutput. Returns true if
  // succeeded and |capture_frame_cb| will be run at some future point. Returns
  // false on error, and |capture_frame_cb| should be run by the caller (with
  // failure status).
  bool ProcessCopyOutputResponse(scoped_refptr<media::VideoFrame> video_frame,
                                 base::TimeTicks event_time,
                                 const CaptureFrameCallback& capture_frame_cb,
                                 std::unique_ptr<cc::CopyOutputResult> result);

  // Renders the cursor if needed and then delivers the captured frame.
  static void CopyOutputFinishedForVideo(
      base::WeakPtr<AuraWindowCaptureMachine> machine,
      base::TimeTicks event_time,
      const CaptureFrameCallback& capture_frame_cb,
      scoped_refptr<media::VideoFrame> target,
      std::unique_ptr<cc::SingleReleaseCallback> release_callback,
      bool result);

  // The window associated with the desktop.
  aura::Window* desktop_window_;

  // Whether screen capturing or window capture.
  bool screen_capture_;

  // Makes all the decisions about which frames to copy, and how.
  scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;

  // The capture parameters for this capture.
  media::VideoCaptureParams capture_params_;

  // YUV readback pipeline.
  std::unique_ptr<display_compositor::ReadbackYUVInterface>
      yuv_readback_pipeline_;

  // Renders mouse cursor on frame.
  std::unique_ptr<content::CursorRendererAura> cursor_renderer_;

  // TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
  // screen from sleeping for the drive-by web.
  std::unique_ptr<device::PowerSaveBlocker> power_save_blocker_;

  // False while frame capture has been suspended. All other aspects of the
  // machine are maintained.
  bool frame_capture_active_;

  // WeakPtrs are used for the asynchronous capture callbacks passed to external
  // modules.  They are only valid on the UI thread and become invalidated
  // immediately when InternalStop() is called to ensure that no more captured
  // frames will be delivered to the client.
  base::WeakPtrFactory<AuraWindowCaptureMachine> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(AuraWindowCaptureMachine);
};

}  // namespace content

#endif  // CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_CAPTURE_MACHINE_H_
