// Copyright (c) 2012 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/stacking_controller.h"

#include "ash/root_window_controller.h"
#include "ash/session/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/window_state.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ui_base_types.h"
#include "ui/wm/core/window_util.h"

namespace ash {
namespace {

// Find a root window that matches the |bounds|. If the virtual screen
// coordinates is enabled and the bounds is specified, the root window
// that matches the window's bound will be used. Otherwise, it'll
// return the active root window.
aura::Window* FindContainerRoot(const gfx::Rect& bounds) {
  if (bounds.x() == 0 && bounds.y() == 0 && bounds.IsEmpty())
    return Shell::GetTargetRootWindow();
  return wm::GetRootWindowMatching(bounds);
}

aura::Window* GetContainerById(aura::Window* root, int id) {
  return Shell::GetContainer(root, id);
}

bool IsSystemModal(aura::Window* window) {
  return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM;
}

bool HasTransientParentWindow(const aura::Window* window) {
  return ::wm::GetTransientParent(window) &&
      ::wm::GetTransientParent(window)->type() !=
      ui::wm::WINDOW_TYPE_UNKNOWN;
}

AlwaysOnTopController* GetAlwaysOnTopController(aura::Window* root_window) {
  return GetRootWindowController(root_window)->always_on_top_controller();
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// StackingController, public:

StackingController::StackingController() {
}

StackingController::~StackingController() {
}

////////////////////////////////////////////////////////////////////////////////
// StackingController, aura::client::WindowTreeClient implementation:

aura::Window* StackingController::GetDefaultParent(aura::Window* context,
                                                   aura::Window* window,
                                                   const gfx::Rect& bounds) {
  aura::Window* target_root = NULL;
  aura::Window* transient_parent = ::wm::GetTransientParent(window);
  if (transient_parent) {
    // Transient window should use the same root as its transient parent.
    target_root = transient_parent->GetRootWindow();
  } else {
    target_root = FindContainerRoot(bounds);
  }

  switch (window->type()) {
    case ui::wm::WINDOW_TYPE_NORMAL:
    case ui::wm::WINDOW_TYPE_POPUP:
      if (IsSystemModal(window))
        return GetSystemModalContainer(target_root, window);
      else if (HasTransientParentWindow(window))
        return RootWindowController::GetContainerForWindow(
            ::wm::GetTransientParent(window));
      return GetAlwaysOnTopController(target_root)->GetContainer(window);
    case ui::wm::WINDOW_TYPE_CONTROL:
      return GetContainerById(target_root,
                              kShellWindowId_UnparentedControlContainer);
    case ui::wm::WINDOW_TYPE_PANEL:
      if (wm::GetWindowState(window)->panel_attached())
        return GetContainerById(target_root, kShellWindowId_PanelContainer);
      else
        return GetAlwaysOnTopController(target_root)->GetContainer(window);
    case ui::wm::WINDOW_TYPE_MENU:
      return GetContainerById(target_root, kShellWindowId_MenuContainer);
    case ui::wm::WINDOW_TYPE_TOOLTIP:
      return GetContainerById(target_root,
                              kShellWindowId_DragImageAndTooltipContainer);
    default:
      NOTREACHED() << "Window " << window->id()
                   << " has unhandled type " << window->type();
      break;
  }
  return NULL;
}

////////////////////////////////////////////////////////////////////////////////
// StackingController, private:

aura::Window* StackingController::GetSystemModalContainer(
    aura::Window* root,
    aura::Window* window) const {
  DCHECK(IsSystemModal(window));

  // If screen lock is not active and user session is active,
  // all modal windows are placed into the normal modal container.
  // In case of missing transient parent (it could happen for alerts from
  // background pages) assume that the window belongs to user session.
  SessionStateDelegate* session_state_delegate =
      Shell::GetInstance()->session_state_delegate();
  if (!session_state_delegate->IsUserSessionBlocked() ||
      !::wm::GetTransientParent(window)) {
    return GetContainerById(root, kShellWindowId_SystemModalContainer);
  }

  // Otherwise those that originate from LockScreen container and above are
  // placed in the screen lock modal container.
  int window_container_id =
      ::wm::GetTransientParent(window)->parent()->id();
  aura::Window* container = NULL;
  if (window_container_id < kShellWindowId_LockScreenContainer) {
    container = GetContainerById(root, kShellWindowId_SystemModalContainer);
  } else {
    container = GetContainerById(root, kShellWindowId_LockSystemModalContainer);
  }

  return container;
}

}  // namespace ash
