// Copyright 2017 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 COMPONENTS_EXO_CLIENT_CONTROLLED_SHELL_SURFACE_H_
#define COMPONENTS_EXO_CLIENT_CONTROLLED_SHELL_SURFACE_H_

#include <memory>
#include <string>

#include "ash/display/screen_orientation_controller.h"
#include "ash/public/cpp/arc_resize_lock_type.h"
#include "ash/wm/client_controlled_state.h"
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "components/exo/client_controlled_accelerators.h"
#include "components/exo/shell_surface_base.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/compositor_lock.h"

namespace ash {
class NonClientFrameViewAsh;
class WideFrameView;
}  // namespace ash

namespace chromeos {
class ImmersiveFullscreenController;
}  // namespace chromeos

namespace exo {
class Surface;
class ClientControlledAcceleratorTarget;

enum class Orientation { PORTRAIT, LANDSCAPE };
enum class ZoomChange { IN, OUT, RESET };

// This class implements a ShellSurface whose window state and bounds are
// controlled by a remote shell client rather than the window manager. The
// position specified as part of the geometry is relative to the origin of
// the screen coordinate system.
class ClientControlledShellSurface : public ShellSurfaceBase,
                                     public ui::CompositorLockClient {
 public:
  // TODO(mukai): integrate this with ShellSurfaceBase's callback.
  class Delegate {
   public:
    virtual ~Delegate() = default;
    virtual void OnGeometryChanged(const gfx::Rect& geometry) = 0;
    virtual void OnStateChanged(chromeos::WindowStateType old_state_type,
                                chromeos::WindowStateType new_state_type) = 0;
    virtual void OnBoundsChanged(chromeos::WindowStateType current_state,
                                 chromeos::WindowStateType requested_state,
                                 int64_t display_id,
                                 const gfx::Rect& bounds_in_display,
                                 bool is_resize,
                                 int bounds_change) = 0;
    virtual void OnDragStarted(int component) = 0;
    virtual void OnDragFinished(int x, int y, bool canceled) = 0;
    virtual void OnZoomLevelChanged(ZoomChange zoom_change) = 0;
  };

  ClientControlledShellSurface(Surface* surface,
                               bool can_minimize,
                               int container,
                               bool default_scale_cancellation);

  ClientControlledShellSurface(const ClientControlledShellSurface&) = delete;
  ClientControlledShellSurface& operator=(const ClientControlledShellSurface&) =
      delete;

  ~ClientControlledShellSurface() override;

  Delegate* set_delegate(std::unique_ptr<Delegate> delegate) {
    delegate_ = std::move(delegate);
    return delegate_.get();
  }

  void set_server_reparent_window(bool reparent) {
    server_reparent_window_ = reparent;
  }

  // Set bounds in root window coordinates relative to the given display.
  void SetBounds(int64_t display_id, const gfx::Rect& bounds);

  // Set origin of bounds for surface while preserving the size.
  void SetBoundsOrigin(int64_t display_id, const gfx::Point& origin);

  // Set size of bounds for surface while preserving the origin.
  void SetBoundsSize(const gfx::Size& size);

  // Called when the client was maximized.
  void SetMaximized();

  // Called when the client was minimized.
  void SetMinimized();

  // Called when the client was restored.
  void SetRestored();

  // Called when the client changed the fullscreen state.
  void SetFullscreen(bool fullscreen);

  // Returns true if this shell surface is currently being dragged.
  bool IsDragging();

  // Pin/unpin the surface. Pinned surface cannot be switched to
  // other windows unless its explicitly unpinned.
  void SetPinned(chromeos::WindowPinType type);

  // Sets the surface to be on top of all other windows.
  void SetAlwaysOnTop(bool always_on_top);

  // Controls the visibility of the system UI when this surface is active.
  void SetSystemUiVisibility(bool autohide);

  // Set orientation for surface.
  void SetOrientation(Orientation orientation);

  // Set shadow bounds in surface coordinates. Empty bounds disable the shadow.
  void SetShadowBounds(const gfx::Rect& bounds);

  // Set the pending scale.
  void SetScale(double scale);

  // Commit the pending scale if it was changed. The scale set by SetScale() is
  // otherwise committed by OnPostWidgetCommit().
  void CommitPendingScale();

  // Set top inset for surface.
  void SetTopInset(int height);

  // Sends the request to change the zoom level to the client.
  void ChangeZoomLevel(ZoomChange change);

  // Sends the window state change event to client.
  void OnWindowStateChangeEvent(chromeos::WindowStateType old_state,
                                chromeos::WindowStateType next_state);

  // Sends the window bounds change event to client. |display_id| specifies in
  // which display the surface should live in. |drag_bounds_change| is
  // a masked value of ash::WindowResizer::kBoundsChange_Xxx, and specifies
  // how the bounds was changed. The bounds change event may also come from a
  // snapped window state change |requested_state|.
  void OnBoundsChangeEvent(chromeos::WindowStateType current_state,
                           chromeos::WindowStateType requested_state,
                           int64_t display_id,
                           const gfx::Rect& bounds,
                           int drag_bounds_change);

  // Sends the window drag events to client.
  void OnDragStarted(int component);
  void OnDragFinished(bool cancel, const gfx::PointF& location);

  // Starts the drag operation.
  void StartDrag(int component, const gfx::PointF& location);

  // Set if the surface can be maximzied.
  void SetCanMaximize(bool can_maximize);

  // Update the auto hide frame state.
  void UpdateAutoHideFrame();

  // Set the frame button state. The |visible_button_mask| and
  // |enabled_button_mask| is a bit mask whose position is defined
  // in views::CaptionButtonIcon enum.
  void SetFrameButtons(uint32_t frame_visible_button_mask,
                       uint32_t frame_enabled_button_mask);

  // Set the extra title for the surface.
  void SetExtraTitle(const std::u16string& extra_title);

  // Set the accessibility ID provided by client for the surface. If
  // |accessibility_id| is negative value, it will unset the ID.
  void SetClientAccessibilityId(int32_t accessibility_id);

  // Rebind a surface as the root surface of the shell surface.
  void RebindRootSurface(Surface* root_surface,
                         bool can_minimize,
                         int container,
                         bool default_scale_cancellation);

  // Overridden from SurfaceTreeHost:
  void DidReceiveCompositorFrameAck() override;

  // Overridden from SurfaceDelegate:
  bool IsInputEnabled(Surface* surface) const override;
  void OnSetFrame(SurfaceFrameType type) override;
  void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override;
  void SetSnappedToPrimary() override;
  void SetSnappedToSecondary() override;
  void SetPip() override;
  void UnsetPip() override;

  // Overridden from views::WidgetDelegate:
  bool CanMaximize() const override;
  std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
      views::Widget* widget) override;
  bool ShouldSaveWindowPlacement() const override;
  void SaveWindowPlacement(const gfx::Rect& bounds,
                           ui::WindowShowState show_state) override;
  bool GetSavedWindowPlacement(const views::Widget* widget,
                               gfx::Rect* bounds,
                               ui::WindowShowState* show_state) const override;

  // Overridden from views::View:
  gfx::Size GetMaximumSize() const override;
  void OnDeviceScaleFactorChanged(float old_dsf, float new_dsf) override;

  // Overridden from aura::WindowObserver:
  void OnWindowAddedToRootWindow(aura::Window* window) override;

  // Overridden from display::DisplayObserver:
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t changed_metrics) override;

  // Overridden from ui::CompositorLockClient:
  void CompositorLockTimedOut() override;

  // A factory callback to create ClientControlledState::Delegate.
  using DelegateFactoryCallback = base::RepeatingCallback<
      std::unique_ptr<ash::ClientControlledState::Delegate>(void)>;

  // Set the factory callback for unit test.
  static void SetClientControlledStateDelegateFactoryForTest(
      const DelegateFactoryCallback& callback);

  ash::WideFrameView* wide_frame_for_test() { return wide_frame_.get(); }

  // Exposed for testing. Returns the effective scale as opposed to
  // |pending_scale_|.
  double scale() const { return scale_; }

  // Used to scale incoming coordinates from the client to DP.
  float GetClientToDpScale() const;

  // Sets the resize lock type to the surface.
  void SetResizeLockType(ash::ArcResizeLockType resize_lock_type);

  // Update the resizability based on the resize lock type.
  void UpdateResizability() override;

  // Overridden from exo::ShellSurfaceBase
  void SetSystemModal(bool system_modal) override;

 protected:
  // Overridden from ShellSurfaceBase:
  float GetScale() const override;

 private:
  FRIEND_TEST_ALL_PREFIXES(ClientControlledShellSurfaceTest,
                           OverlayShadowBounds);
  class ScopedSetBoundsLocally;
  class ScopedLockedToRoot;

  // Overridden from ShellSurfaceBase:
  void SetWidgetBounds(const gfx::Rect& bounds,
                       bool adjusted_by_server) override;
  gfx::Rect GetShadowBounds() const override;
  void InitializeWindowState(ash::WindowState* window_state) override;
  absl::optional<gfx::Rect> GetWidgetBounds() const override;
  gfx::Point GetSurfaceOrigin() const override;
  bool OnPreWidgetCommit() override;
  void OnPostWidgetCommit() override;
  void OnSurfaceDestroying(Surface* surface) override;
  void OnContentSizeChanged(Surface* surface) override;

  // Update frame status. This may create (or destroy) a wide frame
  // that spans the full work area width if the surface didn't cover
  // the work area.
  void UpdateFrame();

  void UpdateCaptionButtonModel();

  void UpdateBackdrop();

  void UpdateFrameWidth();

  void UpdateFrameType() override;

  bool GetCanResizeFromSizeConstraints() const override;

  void AttemptToStartDrag(int component, const gfx::PointF& location);

  // Lock the compositor if it's not already locked, or extends the
  // lock timeout if it's already locked.
  // TODO(reveman): Remove this when using configure callbacks for orientation.
  // crbug.com/765954
  void EnsureCompositorIsLockedForOrientationChange();

  ash::WindowState* GetWindowState();
  ash::NonClientFrameViewAsh* GetFrameView();
  const ash::NonClientFrameViewAsh* GetFrameView() const;

  void EnsurePendingScale(bool commit_immediately);
  float GetClientToDpPendingScale() const;

  gfx::Rect GetClientBoundsForWindowBoundsAndWindowState(
      const gfx::Rect& window_bounds,
      chromeos::WindowStateType window_state) const;

  int top_inset_height_ = 0;
  int pending_top_inset_height_ = 0;

  double scale_ = 1.0;
  // The pending scale is initialized to 0.0 to indicate that the scale is not
  // yet initialized.
  double pending_scale_ = 0.0;

  uint32_t frame_visible_button_mask_ = 0;
  uint32_t frame_enabled_button_mask_ = 0;

  std::unique_ptr<Delegate> delegate_;

  // TODO(reveman): Use configure callbacks for orientation. crbug.com/765954
  Orientation pending_orientation_ = Orientation::LANDSCAPE;
  Orientation orientation_ = Orientation::LANDSCAPE;
  Orientation expected_orientation_ = Orientation::LANDSCAPE;

  ash::ClientControlledState* client_controlled_state_ = nullptr;

  chromeos::WindowStateType pending_window_state_ =
      chromeos::WindowStateType::kNormal;

  bool pending_always_on_top_ = false;

  SurfaceFrameType pending_frame_type_ = SurfaceFrameType::NONE;

  bool can_maximize_ = true;

  std::unique_ptr<chromeos::ImmersiveFullscreenController>
      immersive_fullscreen_controller_;

  std::unique_ptr<ash::WideFrameView> wide_frame_;

  std::unique_ptr<ui::CompositorLock> orientation_compositor_lock_;

  // The extra title to be applied when widget is being created.
  std::u16string initial_extra_title_ = std::u16string();

  bool preserve_widget_bounds_ = false;

  // Checking DragDetails is not sufficient to determine if a bounds
  // request happened during a drag move or resize. If the window resizer
  // requests a bounds update after completing the drag but before the
  // drag details are cleaned up, we want to consider that as a regular
  // bounds update, not a drag move/resize update.
  bool in_drag_ = false;

  // N uses older protocol which expects that server will reparent the window.
  // TODO(oshima): Remove this once all boards are migrated to P or above.
  bool server_reparent_window_ = false;

  bool ignore_bounds_change_request_ = false;

  bool display_rotating_with_pip_ = false;

  // True if the window state has changed during the commit.
  bool state_changed_ = false;

  // When false, the client handles all display scale changes, so the
  // buffer should be re-scaled to undo any scaling added by exo so that the
  // 1:1 correspondence between the pixels is maintained.
  bool use_default_scale_cancellation_ = false;

  // Client controlled specific accelerator target.
  std::unique_ptr<ClientControlledAcceleratorTarget> accelerator_target_;

  // Accessibility ID provided by client.
  absl::optional<int32_t> client_accessibility_id_;

  ash::ArcResizeLockType pending_resize_lock_type_ =
      ash::ArcResizeLockType::NONE;
};

}  // namespace exo

#endif  // COMPONENTS_EXO_CLIENT_CONTROLLED_SHELL_SURFACE_H_
