// Copyright 2016 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.

#include "ash/wm/screen_pinning_controller.h"

#include <algorithm>
#include <memory>
#include <vector>

#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/window_user_data.h"
#include "ash/wm/container_finder.h"
#include "ash/wm/window_dimmer.h"
#include "ash/wm/window_state.h"
#include "base/auto_reset.h"
#include "base/logging.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/wm/core/window_util.h"

namespace ash {
namespace {

// Returns a list of Windows corresponding to SystemModalContainers,
// except ones whose root is shared with |pinned_window|.
aura::Window::Windows GetSystemModalWindowsExceptPinned(
    aura::Window* pinned_window) {
  aura::Window* pinned_root = pinned_window->GetRootWindow();

  aura::Window::Windows result;
  for (aura::Window* system_modal : wm::GetContainersFromAllRootWindows(
           kShellWindowId_SystemModalContainer)) {
    if (system_modal->GetRootWindow() == pinned_root)
      continue;
    result.push_back(system_modal);
  }
  return result;
}

void AddObserverToChildren(aura::Window* container,
                           aura::WindowObserver* observer) {
  for (aura::Window* child : container->children())
    child->AddObserver(observer);
}

void RemoveObserverFromChildren(aura::Window* container,
                                aura::WindowObserver* observer) {
  for (aura::Window* child : container->children())
    child->RemoveObserver(observer);
}

// Returns true if the aura::Window from a WindowDimmer is visible.
bool IsWindowDimmerWindowVisible(WindowDimmer* window_dimmer) {
  return window_dimmer->window()->layer()->GetTargetVisibility();
}

}  // namespace

// Adapter to fire OnPinnedContainerWindowStackingChanged().
class ScreenPinningController::PinnedContainerChildWindowObserver
    : public aura::WindowObserver {
 public:
  explicit PinnedContainerChildWindowObserver(
      ScreenPinningController* controller)
      : controller_(controller) {}

  void OnWindowStackingChanged(aura::Window* window) override {
    controller_->OnPinnedContainerWindowStackingChanged(window);
  }

 private:
  ScreenPinningController* controller_;
  DISALLOW_COPY_AND_ASSIGN(PinnedContainerChildWindowObserver);
};

// Adapter to translate OnWindowAdded/OnWillRemoveWindow for the container
// containing the pinned window, to the corresponding controller's methods.
class ScreenPinningController::PinnedContainerWindowObserver
    : public aura::WindowObserver {
 public:
  explicit PinnedContainerWindowObserver(ScreenPinningController* controller)
      : controller_(controller) {}

  void OnWindowAdded(aura::Window* new_window) override {
    controller_->OnWindowAddedToPinnedContainer(new_window);
  }
  void OnWillRemoveWindow(aura::Window* window) override {
    controller_->OnWillRemoveWindowFromPinnedContainer(window);
  }
  void OnWindowDestroying(aura::Window* window) override {
    // Just in case. There is nothing we can do here.
    window->RemoveObserver(this);
  }

 private:
  ScreenPinningController* controller_;
  DISALLOW_COPY_AND_ASSIGN(PinnedContainerWindowObserver);
};

// Adapter to fire OnSystemModalContainerWindowStackingChanged().
class ScreenPinningController::SystemModalContainerChildWindowObserver
    : public aura::WindowObserver {
 public:
  explicit SystemModalContainerChildWindowObserver(
      ScreenPinningController* controller)
      : controller_(controller) {}

  void OnWindowStackingChanged(aura::Window* window) override {
    controller_->OnSystemModalContainerWindowStackingChanged(window);
  }

 private:
  ScreenPinningController* controller_;
  DISALLOW_COPY_AND_ASSIGN(SystemModalContainerChildWindowObserver);
};

// Adapter to translate OnWindowAdded/OnWillRemoveWindow for the
// SystemModalContainer to the corresponding controller's methods.
class ScreenPinningController::SystemModalContainerWindowObserver
    : public aura::WindowObserver {
 public:
  explicit SystemModalContainerWindowObserver(
      ScreenPinningController* controller)
      : controller_(controller) {}

  void OnWindowAdded(aura::Window* new_window) override {
    controller_->OnWindowAddedToSystemModalContainer(new_window);
  }
  void OnWillRemoveWindow(aura::Window* window) override {
    controller_->OnWillRemoveWindowFromSystemModalContainer(window);
  }
  void OnWindowDestroying(aura::Window* window) override {
    // Just in case. There is nothing we can do here.
    window->RemoveObserver(this);
  }

 private:
  ScreenPinningController* controller_;
  DISALLOW_COPY_AND_ASSIGN(SystemModalContainerWindowObserver);
};

ScreenPinningController::ScreenPinningController()
    : window_dimmers_(std::make_unique<WindowUserData<WindowDimmer>>()),
      pinned_container_window_observer_(
          std::make_unique<PinnedContainerWindowObserver>(this)),
      pinned_container_child_window_observer_(
          std::make_unique<PinnedContainerChildWindowObserver>(this)),
      system_modal_container_window_observer_(
          std::make_unique<SystemModalContainerWindowObserver>(this)),
      system_modal_container_child_window_observer_(
          std::make_unique<SystemModalContainerChildWindowObserver>(this)) {
  Shell::Get()->window_tree_host_manager()->AddObserver(this);
}

ScreenPinningController::~ScreenPinningController() {
  Shell::Get()->window_tree_host_manager()->RemoveObserver(this);
}

bool ScreenPinningController::IsPinned() const {
  return pinned_window_ != nullptr;
}

void ScreenPinningController::SetPinnedWindow(aura::Window* pinned_window) {
  if (wm::GetWindowState(pinned_window)->IsPinned()) {
    if (pinned_window_) {
      LOG(DFATAL) << "Pinned mode is enabled, while it is already in "
                  << "the pinned mode";
      return;
    }

    aura::Window* container = pinned_window->parent();
    aura::Window::Windows system_modal_containers =
        GetSystemModalWindowsExceptPinned(pinned_window);

    // Set up the container which has the pinned window.
    pinned_window_ = pinned_window;
    container->StackChildAtTop(pinned_window);
    container->StackChildBelow(CreateWindowDimmer(container), pinned_window);

    // Set the dim windows to the system containers, other than the one which
    // the root window of the pinned window holds.
    for (aura::Window* system_modal : system_modal_containers)
      system_modal->StackChildAtBottom(CreateWindowDimmer(system_modal));

    // Set observers.
    container->AddObserver(pinned_container_window_observer_.get());
    AddObserverToChildren(container,
                          pinned_container_child_window_observer_.get());
    for (aura::Window* system_modal : system_modal_containers) {
      system_modal->AddObserver(system_modal_container_window_observer_.get());
      AddObserverToChildren(
          system_modal, system_modal_container_child_window_observer_.get());
    }
  } else {
    if (pinned_window != pinned_window_) {
      LOG(DFATAL) << "Pinned mode is being disabled, but for the different "
                  << "target window.";
      return;
    }

    aura::Window* container = pinned_window->parent();
    aura::Window::Windows system_modal_containers =
        GetSystemModalWindowsExceptPinned(pinned_window_);

    // Unset observers.
    for (aura::Window* system_modal :
         GetSystemModalWindowsExceptPinned(pinned_window_)) {
      RemoveObserverFromChildren(
          system_modal, system_modal_container_child_window_observer_.get());
      system_modal->RemoveObserver(
          system_modal_container_window_observer_.get());
    }
    RemoveObserverFromChildren(container,
                               pinned_container_child_window_observer_.get());
    container->RemoveObserver(pinned_container_window_observer_.get());

    window_dimmers_->clear();
    pinned_window_ = nullptr;
  }

  Shell::Get()->NotifyPinnedStateChanged(pinned_window);
}

void ScreenPinningController::OnWindowAddedToPinnedContainer(
    aura::Window* new_window) {
  KeepPinnedWindowOnTop();
  new_window->AddObserver(pinned_container_child_window_observer_.get());
}

void ScreenPinningController::OnWillRemoveWindowFromPinnedContainer(
    aura::Window* window) {
  window->RemoveObserver(pinned_container_child_window_observer_.get());
  if (window == pinned_window_)
    wm::GetWindowState(pinned_window_)->Restore();
}

void ScreenPinningController::OnPinnedContainerWindowStackingChanged(
    aura::Window* window) {
  KeepPinnedWindowOnTop();
}

void ScreenPinningController::OnWindowAddedToSystemModalContainer(
    aura::Window* new_window) {
  KeepDimWindowAtBottom(new_window->parent());
  new_window->AddObserver(system_modal_container_child_window_observer_.get());
}

void ScreenPinningController::OnWillRemoveWindowFromSystemModalContainer(
    aura::Window* window) {
  window->RemoveObserver(system_modal_container_child_window_observer_.get());
}

void ScreenPinningController::OnSystemModalContainerWindowStackingChanged(
    aura::Window* window) {
  KeepDimWindowAtBottom(window->parent());
}

aura::Window* ScreenPinningController::CreateWindowDimmer(
    aura::Window* container) {
  std::unique_ptr<WindowDimmer> window_dimmer =
      std::make_unique<WindowDimmer>(container);
  window_dimmer->SetDimOpacity(1);  // Fully opaque.
  ::wm::SetWindowFullscreen(window_dimmer->window(), true);
  window_dimmer->window()->Show();
  aura::Window* window = window_dimmer->window();
  window_dimmers_->Set(container, std::move(window_dimmer));
  return window;
}

void ScreenPinningController::OnDisplayConfigurationChanged() {
  // Note: this is called on display attached or detached.
  if (!IsPinned())
    return;

  // On display detaching, all necessary windows are transferred to the
  // primary display's tree, and called this.
  // So, delete WindowDimmers which are not a part of target system modal
  // container.
  // On display attaching, the new system modal container does not have the
  // WindowDimmer. So create it.

  // First, delete unnecessary WindowDimmers.
  for (aura::Window* container : window_dimmers_->GetWindows()) {
    if (container != pinned_window_->parent() &&
        !IsWindowDimmerWindowVisible(window_dimmers_->Get(container))) {
      window_dimmers_->Set(container, nullptr);
    }
  }

  // Then, create missing WindowDimmers.
  aura::Window::Windows system_modal_containers =
      GetSystemModalWindowsExceptPinned(pinned_window_);
  for (aura::Window* system_modal : system_modal_containers) {
    if (window_dimmers_->Get(system_modal)) {
      // |system_modal| already has a WindowDimmer.
      continue;
    }

    // This is the new system modal dialog.
    system_modal->StackChildAtBottom(CreateWindowDimmer(system_modal));

    // Set observers to the tree.
    system_modal->AddObserver(system_modal_container_window_observer_.get());
    AddObserverToChildren(system_modal,
                          system_modal_container_child_window_observer_.get());
  }
}

void ScreenPinningController::KeepPinnedWindowOnTop() {
  if (in_restacking_)
    return;

  base::AutoReset<bool> auto_reset(&in_restacking_, true);
  aura::Window* container = pinned_window_->parent();
  container->StackChildAtTop(pinned_window_);
  WindowDimmer* pinned_window_dimmer = window_dimmers_->Get(container);
  if (pinned_window_dimmer && pinned_window_dimmer->window())
    container->StackChildBelow(pinned_window_dimmer->window(), pinned_window_);
}

void ScreenPinningController::KeepDimWindowAtBottom(aura::Window* container) {
  if (in_restacking_)
    return;

  WindowDimmer* window_dimmer = window_dimmers_->Get(container);
  if (window_dimmer) {
    base::AutoReset<bool> auto_reset(&in_restacking_, true);
    container->StackChildAtBottom(window_dimmer->window());
  }
}

}  // namespace ash
