// 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);
  if (pinned_window_)
    pinned_window_->RemoveObserver(this);
  pinned_window_ = nullptr;
}

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;
    // To monitor destruction.
    pinned_window_->AddObserver(this);
    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_->RemoveObserver(this);
    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());
}

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::OnWindowDestroying(aura::Window* window) {
  DCHECK_EQ(pinned_window_, window);
  WindowState::Get(window)->Restore();
  window->RemoveObserver(this);
  pinned_window_ = nullptr;
}

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
