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

#include "services/ui/ws/display.h"

#include <set>
#include <utility>
#include <vector>

#include "base/debug/debugger.h"
#include "base/strings/utf_string_conversions.h"
#include "mojo/common/common_type_converters.h"
#include "services/shell/public/interfaces/connector.mojom.h"
#include "services/ui/common/types.h"
#include "services/ui/ws/display_binding.h"
#include "services/ui/ws/display_manager.h"
#include "services/ui/ws/focus_controller.h"
#include "services/ui/ws/platform_display.h"
#include "services/ui/ws/platform_display_init_params.h"
#include "services/ui/ws/user_activity_monitor.h"
#include "services/ui/ws/window_manager_display_root.h"
#include "services/ui/ws/window_manager_state.h"
#include "services/ui/ws/window_manager_window_tree_factory.h"
#include "services/ui/ws/window_server.h"
#include "services/ui/ws/window_server_delegate.h"
#include "services/ui/ws/window_tree.h"
#include "services/ui/ws/window_tree_binding.h"
#include "ui/base/cursor/cursor.h"

namespace ui {
namespace ws {

Display::Display(WindowServer* window_server,
                 const PlatformDisplayInitParams& platform_display_init_params)
    : id_(window_server->display_manager()->GetAndAdvanceNextDisplayId()),
      window_server_(window_server),
      platform_display_(PlatformDisplay::Create(platform_display_init_params)),
      last_cursor_(ui::kCursorNone) {
  platform_display_->Init(this);

  window_server_->window_manager_window_tree_factory_set()->AddObserver(this);
  window_server_->user_id_tracker()->AddObserver(this);
}

Display::~Display() {
  window_server_->user_id_tracker()->RemoveObserver(this);

  window_server_->window_manager_window_tree_factory_set()->RemoveObserver(
      this);

  if (!focus_controller_) {
    focus_controller_->RemoveObserver(this);
    focus_controller_.reset();
  }

  for (ServerWindow* window : windows_needing_frame_destruction_)
    window->RemoveObserver(this);

  // If there is a |binding_| then the tree was created specifically for this
  // display (which corresponds to a WindowTreeHost).
  if (binding_ && !window_manager_display_root_map_.empty()) {
    window_server_->DestroyTree(window_manager_display_root_map_.begin()
                                    ->second->window_manager_state()
                                    ->window_tree());
  }
}

void Display::Init(std::unique_ptr<DisplayBinding> binding) {
  init_called_ = true;
  binding_ = std::move(binding);
  display_manager()->AddDisplay(this);
  InitWindowManagerDisplayRootsIfNecessary();
}

DisplayManager* Display::display_manager() {
  return window_server_->display_manager();
}

const DisplayManager* Display::display_manager() const {
  return window_server_->display_manager();
}

mojom::WsDisplayPtr Display::ToWsDisplay() const {
  mojom::WsDisplayPtr display_ptr = mojom::WsDisplay::New();

  display_ptr->display = ToDisplay();

  // TODO(sky): make this real.
  display_ptr->is_primary = true;
  // TODO(sky): make this real.
  display_ptr->frame_decoration_values = mojom::FrameDecorationValues::New();
  return display_ptr;
}

::display::Display Display::ToDisplay() const {
  ::display::Display display(id_);

  // TODO(sky): Display should know its origin.
  display.set_bounds(gfx::Rect(0, 0, root_->bounds().size().width(),
                               root_->bounds().size().height()));
  // TODO(sky): window manager needs an API to set the work area.
  display.set_work_area(display.bounds());
  display.set_device_scale_factor(platform_display_->GetDeviceScaleFactor());
  display.set_rotation(platform_display_->GetRotation());
  display.set_touch_support(
      ::display::Display::TouchSupport::TOUCH_SUPPORT_UNKNOWN);

  return display;
}

void Display::SchedulePaint(const ServerWindow* window,
                            const gfx::Rect& bounds) {
  DCHECK(root_->Contains(window));
  platform_display_->SchedulePaint(window, bounds);
}

void Display::ScheduleSurfaceDestruction(ServerWindow* window) {
  if (!platform_display_->IsFramePending()) {
    window->DestroySurfacesScheduledForDestruction();
    return;
  }
  if (windows_needing_frame_destruction_.count(window))
    return;
  windows_needing_frame_destruction_.insert(window);
  window->AddObserver(this);
}

::display::Display::Rotation Display::GetRotation() const {
  return platform_display_->GetRotation();
}

gfx::Size Display::GetSize() const {
  return root_->bounds().size();
}

int64_t Display::GetPlatformDisplayId() const {
  return platform_display_->GetDisplayId();
}

ServerWindow* Display::GetRootWithId(const WindowId& id) {
  if (id == root_->id())
    return root_.get();
  for (auto& pair : window_manager_display_root_map_) {
    if (pair.second->root()->id() == id)
      return pair.second->root();
  }
  return nullptr;
}

WindowManagerDisplayRoot* Display::GetWindowManagerDisplayRootWithRoot(
    const ServerWindow* window) {
  for (auto& pair : window_manager_display_root_map_) {
    if (pair.second->root() == window)
      return pair.second.get();
  }
  return nullptr;
}

const WindowManagerDisplayRoot* Display::GetWindowManagerDisplayRootForUser(
    const UserId& user_id) const {
  auto iter = window_manager_display_root_map_.find(user_id);
  return iter == window_manager_display_root_map_.end() ? nullptr
                                                        : iter->second.get();
}

const WindowManagerDisplayRoot* Display::GetActiveWindowManagerDisplayRoot()
    const {
  return GetWindowManagerDisplayRootForUser(
      window_server_->user_id_tracker()->active_id());
}

bool Display::SetFocusedWindow(ServerWindow* new_focused_window) {
  ServerWindow* old_focused_window = focus_controller_->GetFocusedWindow();
  if (old_focused_window == new_focused_window)
    return true;
  DCHECK(!new_focused_window || root_window()->Contains(new_focused_window));
  return focus_controller_->SetFocusedWindow(new_focused_window);
}

ServerWindow* Display::GetFocusedWindow() {
  return focus_controller_->GetFocusedWindow();
}

void Display::ActivateNextWindow() {
  // TODO(sky): this is wrong, needs to figure out the next window to activate
  // and then route setting through WindowServer.
  focus_controller_->ActivateNextWindow();
}

void Display::AddActivationParent(ServerWindow* window) {
  activation_parents_.Add(window);
}

void Display::RemoveActivationParent(ServerWindow* window) {
  activation_parents_.Remove(window);
}

void Display::UpdateTextInputState(ServerWindow* window,
                                   const ui::TextInputState& state) {
  // Do not need to update text input for unfocused windows.
  if (!platform_display_ || focus_controller_->GetFocusedWindow() != window)
    return;
  platform_display_->UpdateTextInputState(state);
}

void Display::SetImeVisibility(ServerWindow* window, bool visible) {
  // Do not need to show or hide IME for unfocused window.
  if (focus_controller_->GetFocusedWindow() != window)
    return;
  platform_display_->SetImeVisibility(visible);
}

void Display::OnWillDestroyTree(WindowTree* tree) {
  for (auto it = window_manager_display_root_map_.begin();
       it != window_manager_display_root_map_.end(); ++it) {
    if (it->second->window_manager_state()->window_tree() == tree) {
      window_manager_display_root_map_.erase(it);
      break;
    }
  }
}

void Display::UpdateNativeCursor(int32_t cursor_id) {
  if (cursor_id != last_cursor_) {
    platform_display_->SetCursorById(cursor_id);
    last_cursor_ = cursor_id;
  }
}

void Display::SetSize(const gfx::Size& size) {
  platform_display_->SetViewportSize(size);
}

void Display::SetTitle(const mojo::String& title) {
  platform_display_->SetTitle(title.To<base::string16>());
}

void Display::InitWindowManagerDisplayRootsIfNecessary() {
  if (!init_called_ || !root_)
    return;

  display_manager()->OnDisplayAcceleratedWidgetAvailable(this);
  if (binding_) {
    std::unique_ptr<WindowManagerDisplayRoot> display_root_ptr(
        new WindowManagerDisplayRoot(this));
    WindowManagerDisplayRoot* display_root = display_root_ptr.get();
    // For this case we never create additional displays roots, so any
    // id works.
    window_manager_display_root_map_[shell::mojom::kRootUserID] =
        std::move(display_root_ptr);
    WindowTree* window_tree = binding_->CreateWindowTree(display_root->root());
    display_root->window_manager_state_ = window_tree->window_manager_state();
  } else {
    CreateWindowManagerDisplayRootsFromFactories();
  }
}

void Display::CreateWindowManagerDisplayRootsFromFactories() {
  std::vector<WindowManagerWindowTreeFactory*> factories =
      window_server_->window_manager_window_tree_factory_set()->GetFactories();
  for (WindowManagerWindowTreeFactory* factory : factories) {
    if (factory->window_tree())
      CreateWindowManagerDisplayRootFromFactory(factory);
  }
}

void Display::CreateWindowManagerDisplayRootFromFactory(
    WindowManagerWindowTreeFactory* factory) {
  std::unique_ptr<WindowManagerDisplayRoot> display_root_ptr(
      new WindowManagerDisplayRoot(this));
  WindowManagerDisplayRoot* display_root = display_root_ptr.get();
  window_manager_display_root_map_[factory->user_id()] =
      std::move(display_root_ptr);
  display_root->window_manager_state_ =
      factory->window_tree()->window_manager_state();
  const bool is_active =
      factory->user_id() == window_server_->user_id_tracker()->active_id();
  display_root->root()->SetVisible(is_active);
  display_root->window_manager_state()->window_tree()->AddRootForWindowManager(
      display_root->root());
}

ServerWindow* Display::GetRootWindow() {
  return root_.get();
}

bool Display::IsInHighContrastMode() {
  return window_server_->IsActiveUserInHighContrastMode();
}

void Display::OnEvent(const ui::Event& event) {
  WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
  if (display_root)
    display_root->window_manager_state()->ProcessEvent(event);
  window_server_
      ->GetUserActivityMonitorForUser(
          window_server_->user_id_tracker()->active_id())
      ->OnUserActivity();
}

void Display::OnNativeCaptureLost() {
  WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
  if (display_root)
    display_root->window_manager_state()->SetCapture(nullptr, kInvalidClientId);
}

void Display::OnDisplayClosed() {
  display_manager()->DestroyDisplay(this);
}

void Display::OnViewportMetricsChanged(const ViewportMetrics& old_metrics,
                                       const ViewportMetrics& new_metrics) {
  if (!root_) {
    root_.reset(window_server_->CreateServerWindow(
        display_manager()->GetAndAdvanceNextRootId(),
        ServerWindow::Properties()));
    root_->SetBounds(new_metrics.bounds);
    root_->SetVisible(true);
    focus_controller_.reset(new FocusController(this, root_.get()));
    focus_controller_->AddObserver(this);
    InitWindowManagerDisplayRootsIfNecessary();
  } else {
    root_->SetBounds(new_metrics.bounds);
    const gfx::Rect wm_bounds(root_->bounds().size());
    for (auto& pair : window_manager_display_root_map_)
      pair.second->root()->SetBounds(wm_bounds);
  }
  display_manager()->OnDisplayUpdate(this);
}

void Display::OnCompositorFrameDrawn() {
  std::set<ServerWindow*> windows;
  windows.swap(windows_needing_frame_destruction_);
  for (ServerWindow* window : windows) {
    window->RemoveObserver(this);
    window->DestroySurfacesScheduledForDestruction();
  }
}

bool Display::CanHaveActiveChildren(ServerWindow* window) const {
  return window && activation_parents_.Contains(window);
}

void Display::OnActivationChanged(ServerWindow* old_active_window,
                                  ServerWindow* new_active_window) {
  DCHECK_NE(new_active_window, old_active_window);
  if (new_active_window && new_active_window->parent()) {
    // Raise the new active window.
    // TODO(sad): Let the WM dictate whether to raise the window or not?
    new_active_window->parent()->StackChildAtTop(new_active_window);
  }
}

void Display::OnFocusChanged(FocusControllerChangeSource change_source,
                             ServerWindow* old_focused_window,
                             ServerWindow* new_focused_window) {
  // TODO(sky): focus is global, not per windowtreehost. Move.

  // There are up to four clients that need to be notified:
  // . the client containing |old_focused_window|.
  // . the client with |old_focused_window| as its root.
  // . the client containing |new_focused_window|.
  // . the client with |new_focused_window| as its root.
  // Some of these client may be the same. The following takes care to notify
  // each only once.
  WindowTree* owning_tree_old = nullptr;
  WindowTree* embedded_tree_old = nullptr;

  if (old_focused_window) {
    owning_tree_old =
        window_server_->GetTreeWithId(old_focused_window->id().client_id);
    if (owning_tree_old) {
      owning_tree_old->ProcessFocusChanged(old_focused_window,
                                           new_focused_window);
    }
    embedded_tree_old = window_server_->GetTreeWithRoot(old_focused_window);
    if (embedded_tree_old) {
      DCHECK_NE(owning_tree_old, embedded_tree_old);
      embedded_tree_old->ProcessFocusChanged(old_focused_window,
                                             new_focused_window);
    }
  }
  WindowTree* owning_tree_new = nullptr;
  WindowTree* embedded_tree_new = nullptr;
  if (new_focused_window) {
    owning_tree_new =
        window_server_->GetTreeWithId(new_focused_window->id().client_id);
    if (owning_tree_new && owning_tree_new != owning_tree_old &&
        owning_tree_new != embedded_tree_old) {
      owning_tree_new->ProcessFocusChanged(old_focused_window,
                                           new_focused_window);
    }
    embedded_tree_new = window_server_->GetTreeWithRoot(new_focused_window);
    if (embedded_tree_new && embedded_tree_new != owning_tree_old &&
        embedded_tree_new != embedded_tree_old) {
      DCHECK_NE(owning_tree_new, embedded_tree_new);
      embedded_tree_new->ProcessFocusChanged(old_focused_window,
                                             new_focused_window);
    }
  }

  // WindowManagers are always notified of focus changes.
  WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot();
  if (display_root) {
    WindowTree* wm_tree = display_root->window_manager_state()->window_tree();
    if (wm_tree != owning_tree_old && wm_tree != embedded_tree_old &&
        wm_tree != owning_tree_new && wm_tree != embedded_tree_new) {
      wm_tree->ProcessFocusChanged(old_focused_window, new_focused_window);
    }
  }

  UpdateTextInputState(new_focused_window,
                       new_focused_window->text_input_state());
}

void Display::OnWindowDestroyed(ServerWindow* window) {
  windows_needing_frame_destruction_.erase(window);
  window->RemoveObserver(this);
}

void Display::OnUserIdRemoved(const UserId& id) {
  window_manager_display_root_map_.erase(id);
}

void Display::OnWindowManagerWindowTreeFactoryReady(
    WindowManagerWindowTreeFactory* factory) {
  if (!binding_)
    CreateWindowManagerDisplayRootFromFactory(factory);
}

}  // namespace ws
}  // namespace ui
