// 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/always_on_top_controller.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 :
       GetContainersForAllRootWindows(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 (WindowState::Get(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;
    AlwaysOnTopController::SetDisallowReparent(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_)
    WindowState::Get(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.
  AlwaysOnTopController::SetDisallowReparent(window_dimmer->window());
  ::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
