// 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/base_layout_manager.h"

#include "ash/screen_ash.h"
#include "ash/session_state_delegate.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_properties.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/screen.h"
#include "ui/views/corewm/corewm_switches.h"
#include "ui/views/corewm/window_util.h"

namespace ash {
namespace internal {

/////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, public:

BaseLayoutManager::BaseLayoutManager(aura::Window* root_window)
    : root_window_(root_window) {
  Shell::GetInstance()->activation_client()->AddObserver(this);
  Shell::GetInstance()->AddShellObserver(this);
  root_window_->AddObserver(this);
}

BaseLayoutManager::~BaseLayoutManager() {
  if (root_window_)
    root_window_->RemoveObserver(this);
  for (WindowSet::const_iterator i = windows_.begin(); i != windows_.end(); ++i)
    (*i)->RemoveObserver(this);
  Shell::GetInstance()->RemoveShellObserver(this);
  Shell::GetInstance()->activation_client()->RemoveObserver(this);
}

// static
gfx::Rect BaseLayoutManager::BoundsWithScreenEdgeVisible(
    aura::Window* window,
    const gfx::Rect& restore_bounds) {
  gfx::Rect max_bounds =
      ash::ScreenAsh::GetMaximizedWindowBoundsInParent(window);
  // If the restore_bounds are more than 1 grid step away from the size the
  // window would be when maximized, inset it.
  max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset,
                   ash::internal::WorkspaceWindowResizer::kScreenEdgeInset);
  if (restore_bounds.Contains(max_bounds))
    return max_bounds;
  return restore_bounds;
}

/////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, aura::LayoutManager overrides:

void BaseLayoutManager::OnWindowResized() {
}

void BaseLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
  windows_.insert(child);
  child->AddObserver(this);
  wm::WindowState* window_state = wm::GetWindowState(child);
  window_state->AddObserver(this);

  // Only update the bounds if the window has a show state that depends on the
  // workspace area.
  if (window_state->IsMaximizedOrFullscreen())
    UpdateBoundsFromShowState(window_state);
}

void BaseLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
  windows_.erase(child);
  child->RemoveObserver(this);
  wm::GetWindowState(child)->RemoveObserver(this);
}

void BaseLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
}

void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
                                                       bool visible) {
  wm::WindowState* window_state = wm::GetWindowState(child);
  // Attempting to show a minimized window. Unminimize it.
  if (visible && window_state->IsMinimized())
    window_state->Unminimize();
}

void BaseLayoutManager::SetChildBounds(aura::Window* child,
                                       const gfx::Rect& requested_bounds) {
  gfx::Rect child_bounds(requested_bounds);
  wm::WindowState* window_state = wm::GetWindowState(child);
  // Some windows rely on this to set their initial bounds.
  if (window_state->IsMaximized())
    child_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(child);
  else if (window_state->IsFullscreen())
    child_bounds = ScreenAsh::GetDisplayBoundsInParent(child);
  SetChildBoundsDirect(child, child_bounds);
}

/////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, aura::WindowObserver overrides:

void BaseLayoutManager::OnWindowDestroying(aura::Window* window) {
  if (root_window_ == window) {
    root_window_->RemoveObserver(this);
    root_window_ = NULL;
  }
}

void BaseLayoutManager::OnWindowBoundsChanged(aura::Window* window,
                                              const gfx::Rect& old_bounds,
                                              const gfx::Rect& new_bounds) {
  if (root_window_ == window)
    AdjustAllWindowsBoundsForWorkAreaChange(ADJUST_WINDOW_DISPLAY_SIZE_CHANGED);
}

//////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, aura::client::ActivationChangeObserver implementation:

void BaseLayoutManager::OnWindowActivated(aura::Window* gained_active,
                                          aura::Window* lost_active) {
  wm::WindowState* window_state = wm::GetWindowState(gained_active);
  if (window_state && window_state->IsMinimized() &&
      !gained_active->IsVisible()) {
    gained_active->Show();
    DCHECK(!window_state->IsMinimized());
  }
}

/////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, ash::ShellObserver overrides:

void BaseLayoutManager::OnDisplayWorkAreaInsetsChanged() {
  AdjustAllWindowsBoundsForWorkAreaChange(
      ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED);
}

/////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, ash::wm::WindowStateObserver overrides:

void BaseLayoutManager::OnWindowShowTypeChanged(wm::WindowState* window_state,
                                                wm::WindowShowType old_type) {
  ui::WindowShowState old_state = ToWindowShowState(old_type);
  ui::WindowShowState new_state = window_state->GetShowState();

  if (old_state != new_state && old_state != ui::SHOW_STATE_MINIMIZED &&
      !window_state->HasRestoreBounds() &&
      ((new_state == ui::SHOW_STATE_MAXIMIZED &&
        old_state != ui::SHOW_STATE_FULLSCREEN) ||
       (new_state == ui::SHOW_STATE_FULLSCREEN &&
        old_state != ui::SHOW_STATE_MAXIMIZED))) {
    window_state->SetRestoreBoundsInParent(window_state->window()->bounds());
  }

  UpdateBoundsFromShowState(window_state);
  ShowStateChanged(window_state, old_state);
}

//////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, protected:

void BaseLayoutManager::ShowStateChanged(
    wm::WindowState* window_state,
    ui::WindowShowState last_show_state) {
  if (window_state->IsMinimized()) {
    // Save the previous show state so that we can correctly restore it.
    window_state->window()->SetProperty(aura::client::kRestoreShowStateKey,
                                        last_show_state);
    views::corewm::SetWindowVisibilityAnimationType(
        window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);

    // Hide the window.
    window_state->window()->Hide();
    // Activate another window.
    if (window_state->IsActive())
      window_state->Deactivate();
  } else if ((window_state->window()->TargetVisibility() ||
              last_show_state == ui::SHOW_STATE_MINIMIZED) &&
             !window_state->window()->layer()->visible()) {
    // The layer may be hidden if the window was previously minimized. Make
    // sure it's visible.
    window_state->window()->Show();
    if (last_show_state == ui::SHOW_STATE_MINIMIZED &&
        !window_state->IsMaximizedOrFullscreen()) {
      window_state->set_always_restores_to_restore_bounds(false);
    }
  }
}

void BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange(
    AdjustWindowReason reason) {
  // Don't do any adjustments of the insets while we are in screen locked mode.
  // This would happen if the launcher was auto hidden before the login screen
  // was shown and then gets shown when the login screen gets presented.
  if (reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED &&
      Shell::GetInstance()->session_state_delegate()->IsScreenLocked())
    return;

  // If a user plugs an external display into a laptop running Aura the
  // display size will change.  Maximized windows need to resize to match.
  // We also do this when developers running Aura on a desktop manually resize
  // the host window.
  // We also need to do this when the work area insets changes.
  for (WindowSet::const_iterator it = windows_.begin();
       it != windows_.end();
       ++it) {
    AdjustWindowBoundsForWorkAreaChange(wm::GetWindowState(*it), reason);
  }
}

void BaseLayoutManager::AdjustWindowBoundsForWorkAreaChange(
    wm::WindowState* window_state,
    AdjustWindowReason reason) {
  aura::Window* window = window_state->window();
  if (window_state->IsMaximized()) {
    SetChildBoundsDirect(
        window, ScreenAsh::GetMaximizedWindowBoundsInParent(window));
  } else if (window_state->IsFullscreen()) {
    SetChildBoundsDirect(
        window, ScreenAsh::GetDisplayBoundsInParent(window));
  } else {
    // The work area may be smaller than the full screen.
    gfx::Rect display_rect =
        ScreenAsh::GetDisplayWorkAreaBoundsInParent(window);
    // Put as much of the window as possible within the display area.
    gfx::Rect bounds = window->bounds();
    bounds.AdjustToFit(display_rect);
    window->SetBounds(bounds);
  }
}

//////////////////////////////////////////////////////////////////////////////
// BaseLayoutManager, private:

void BaseLayoutManager::UpdateBoundsFromShowState(
    wm::WindowState* window_state) {
  aura::Window* window = window_state->window();
  switch (window_state->GetShowState()) {
    case ui::SHOW_STATE_DEFAULT:
    case ui::SHOW_STATE_NORMAL: {
      if (window_state->HasRestoreBounds()) {
        gfx::Rect bounds_in_parent = window_state->GetRestoreBoundsInParent();
        SetChildBoundsDirect(window,
                             BoundsWithScreenEdgeVisible(window,
                                                         bounds_in_parent));
      }
      window_state->ClearRestoreBounds();
      break;
    }

    case ui::SHOW_STATE_MAXIMIZED:
      SetChildBoundsDirect(
          window, ScreenAsh::GetMaximizedWindowBoundsInParent(window));
      break;

    case ui::SHOW_STATE_FULLSCREEN:
      // Don't animate the full-screen window transition.
      // TODO(jamescook): Use animation here.  Be sure the lock screen works.
      SetChildBoundsDirect(window,
                           ScreenAsh::GetDisplayBoundsInParent(window));
      break;

    default:
      break;
  }
}

}  // namespace internal
}  // namespace ash
