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

#include <utility>

#include "ash/public/cpp/shell_window_ids.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/wm/desks/desks_util.h"
#include "ash/wm/fullscreen_window_finder.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/wm_window_animations.h"
#include "ash/wm/workspace/backdrop_controller.h"
#include "ash/wm/workspace/backdrop_delegate.h"
#include "ash/wm/workspace/workspace_event_handler.h"
#include "ash/wm/workspace/workspace_layout_manager.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/wm/core/window_animations.h"

// Defines a window property to store a WorkspaceController in the properties of
// virtual desks container windows.
ASH_EXPORT extern const aura::WindowProperty<ash::WorkspaceController*>* const
    kWorkspaceController;

DEFINE_UI_CLASS_PROPERTY_TYPE(ash::WorkspaceController*)

DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(ash::WorkspaceController,
                                   kWorkspaceController,
                                   nullptr)

namespace ash {
namespace {

// Amount of time to pause before animating anything. Only used during initial
// animation (when logging in).
const int kInitialPauseTimeMS = 750;

// The duration of the animation that occurs on first login.
const int kInitialAnimationDurationMS = 200;

}  // namespace

WorkspaceController::WorkspaceController(aura::Window* viewport)
    : viewport_(viewport),
      event_handler_(std::make_unique<WorkspaceEventHandler>(viewport)),
      layout_manager_(new WorkspaceLayoutManager(viewport)) {
  viewport_->AddObserver(this);
  ::wm::SetWindowVisibilityAnimationTransition(viewport_, ::wm::ANIMATE_NONE);
  viewport_->SetLayoutManager(layout_manager_);
}

WorkspaceController::~WorkspaceController() {
  if (!viewport_)
    return;

  viewport_->RemoveObserver(this);
  viewport_->SetLayoutManager(nullptr);
}

wm::WorkspaceWindowState WorkspaceController::GetWindowState() const {
  if (!viewport_)
    return wm::WORKSPACE_WINDOW_STATE_DEFAULT;

  // Always use DEFAULT state in overview mode so that work area stays
  // the same regardles of the window we have.
  // The |overview_controller| can be null during shutdown.
  if (Shell::Get()->overview_controller() &&
      Shell::Get()->overview_controller()->IsSelecting()) {
    return wm::WORKSPACE_WINDOW_STATE_DEFAULT;
  }

  const aura::Window* fullscreen =
      wm::GetWindowForFullscreenModeForContext(viewport_);
  if (fullscreen)
    return wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN;

  auto mru_list =
      Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal();

  for (aura::Window* window : mru_list) {
    if (window->GetRootWindow() != viewport_->GetRootWindow())
      continue;
    wm::WindowState* window_state = wm::GetWindowState(window);
    if (window->layer() && !window->layer()->GetTargetVisibility())
      continue;
    if (window_state->IsMaximized())
      return wm::WORKSPACE_WINDOW_STATE_MAXIMIZED;
  }
  return wm::WORKSPACE_WINDOW_STATE_DEFAULT;
}

void WorkspaceController::DoInitialAnimation() {
  viewport_->Show();

  ui::Layer* layer = viewport_->layer();
  layer->SetOpacity(0.0f);
  SetTransformForScaleAnimation(layer, LAYER_SCALE_ANIMATION_ABOVE);

  // In order for pause to work we need to stop animations.
  layer->GetAnimator()->StopAnimating();

  {
    ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());

    settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
    layer->GetAnimator()->SchedulePauseForProperties(
        base::TimeDelta::FromMilliseconds(kInitialPauseTimeMS),
        ui::LayerAnimationElement::TRANSFORM |
            ui::LayerAnimationElement::OPACITY |
            ui::LayerAnimationElement::BRIGHTNESS |
            ui::LayerAnimationElement::VISIBILITY);
    settings.SetTweenType(gfx::Tween::EASE_OUT);
    settings.SetTransitionDuration(
        base::TimeDelta::FromMilliseconds(kInitialAnimationDurationMS));
    layer->SetTransform(gfx::Transform());
    layer->SetOpacity(1.0f);
  }
}

void WorkspaceController::SetBackdropDelegate(
    std::unique_ptr<BackdropDelegate> delegate) {
  layout_manager_->SetBackdropDelegate(std::move(delegate));
}

void WorkspaceController::OnWindowDestroying(aura::Window* window) {
  DCHECK_EQ(window, viewport_);
  viewport_->RemoveObserver(this);
  viewport_ = nullptr;
  // Destroy |event_handler_| too as it depends upon |window|.
  event_handler_.reset();
  layout_manager_ = nullptr;
}

void SetWorkspaceController(aura::Window* desk_container,
                            WorkspaceController* workspace_controller) {
  DCHECK(desk_container);
  DCHECK(desks_util::IsDeskContainer(desk_container));

  if (workspace_controller)
    desk_container->SetProperty(kWorkspaceController, workspace_controller);
  else
    desk_container->ClearProperty(kWorkspaceController);
}

WorkspaceController* GetWorkspaceController(aura::Window* desk_container) {
  DCHECK(desk_container);
  DCHECK(desks_util::IsDeskContainer(desk_container));

  return desk_container->GetProperty(kWorkspaceController);
}

WorkspaceController* GetWorkspaceControllerForContext(aura::Window* context) {
  DCHECK(!context->IsRootWindow());

  // Find the desk container to which |context| belongs.
  while (context && !desks_util::IsDeskContainer(context))
    context = context->parent();

  if (!context)
    return nullptr;

  return GetWorkspaceController(context);
}

WorkspaceController* GetActiveWorkspaceController(aura::Window* root) {
  DCHECK(root->IsRootWindow());

  return GetWorkspaceController(
      desks_util::GetActiveDeskContainerForRoot(root));
}

}  // namespace ash
