// Copyright 2013 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/shelf/shelf_window_watcher.h"

#include "ash/display/display_controller.h"
#include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_item_delegate_manager.h"
#include "ash/shelf/shelf_model.h"
#include "ash/shelf/shelf_util.h"
#include "ash/shelf/shelf_window_watcher_item_delegate.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/screen.h"
#include "ui/wm/public/activation_client.h"

namespace {

// Sets ShelfItem property by using the value of |details|.
void SetShelfItemDetailsForShelfItem(ash::ShelfItem* item,
                                     const ash::ShelfItemDetails& details) {
  item->type = details.type;
  if (details.image_resource_id != ash::kInvalidImageResourceID) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    item->image = *rb.GetImageSkiaNamed(details.image_resource_id);
  }
}

// Returns true if |window| has a ShelfItem added by ShelfWindowWatcher.
bool HasShelfItemForWindow(aura::Window* window) {
  if (ash::GetShelfItemDetailsForWindow(window) != NULL &&
      ash::GetShelfIDForWindow(window) != ash::kInvalidShelfID)
    return true;
  return false;
}

// Returns true if |window| is in the process of being dragged.
bool IsDragging(aura::Window* window) {
  return ash::wm::GetWindowState(window)->is_dragged();
}

}  // namespace

namespace ash {

ShelfWindowWatcher::RootWindowObserver::RootWindowObserver(
    ShelfWindowWatcher* window_watcher)
    : window_watcher_(window_watcher) {
}

ShelfWindowWatcher::RootWindowObserver::~RootWindowObserver() {
}

void ShelfWindowWatcher::RootWindowObserver::OnWindowDestroying(
    aura::Window* window) {
  window_watcher_->OnRootWindowRemoved(window);
}

ShelfWindowWatcher::RemovedWindowObserver::RemovedWindowObserver(
    ShelfWindowWatcher* window_watcher)
    : window_watcher_(window_watcher) {
}

ShelfWindowWatcher::RemovedWindowObserver::~RemovedWindowObserver() {
}

void ShelfWindowWatcher::RemovedWindowObserver::OnWindowParentChanged(
    aura::Window* window,
    aura::Window* parent) {
  // When |parent| is NULL, this |window| will be destroyed. In that case, its
  // item will be removed at OnWindowDestroyed().
  if (!parent)
    return;

  // When |parent| is changed from default container to docked container
  // during the dragging, |window|'s item should not be removed because it will
  // be re-parented to default container again after finishing the dragging.
  // We don't need to check |parent| is default container because this observer
  // is already removed from |window| when |window| is re-parented to default
  // container.
  if (IsDragging(window) && parent->id() == kShellWindowId_DockedContainer)
    return;

  // When |window| is re-parented to other containers or |window| is re-parented
  // not to |docked_container| during the dragging, its item should be removed
  // and stop observing this |window|.
  window_watcher_->FinishObservingRemovedWindow(window);
}

void ShelfWindowWatcher::RemovedWindowObserver::OnWindowDestroyed(
    aura::Window* window) {
  DCHECK(HasShelfItemForWindow(window));
  window_watcher_->FinishObservingRemovedWindow(window);
}

ShelfWindowWatcher::ShelfWindowWatcher(
    ShelfModel* model,
    ShelfItemDelegateManager* item_delegate_manager)
    : model_(model),
      item_delegate_manager_(item_delegate_manager),
      root_window_observer_(this),
      removed_window_observer_(this),
      observed_windows_(this),
      observed_root_windows_(&root_window_observer_),
      observed_removed_windows_(&removed_window_observer_),
      observed_activation_clients_(this) {
  // We can't assume all RootWindows have the same ActivationClient.
  // Add a RootWindow and its ActivationClient to the observed list.
  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  for (aura::Window::Windows::const_iterator it = root_windows.begin();
       it != root_windows.end(); ++it)
    OnRootWindowAdded(*it);

  Shell::GetScreen()->AddObserver(this);
}

ShelfWindowWatcher::~ShelfWindowWatcher() {
  Shell::GetScreen()->RemoveObserver(this);
}

void ShelfWindowWatcher::AddShelfItem(aura::Window* window) {
  const ShelfItemDetails* item_details =
      GetShelfItemDetailsForWindow(window);
  ShelfItem item;
  ShelfID id = model_->next_id();
  item.status = wm::IsActiveWindow(window) ? STATUS_ACTIVE: STATUS_RUNNING;
  SetShelfItemDetailsForShelfItem(&item, *item_details);
  SetShelfIDForWindow(id, window);
  scoped_ptr<ShelfItemDelegate> item_delegate(
      new ShelfWindowWatcherItemDelegate(window, model_));
  // |item_delegate| is owned by |item_delegate_manager_|.
  item_delegate_manager_->SetShelfItemDelegate(id, item_delegate.Pass());
  model_->Add(item);
}

void ShelfWindowWatcher::RemoveShelfItem(aura::Window* window) {
  model_->RemoveItemAt(model_->ItemIndexByID(GetShelfIDForWindow(window)));
  SetShelfIDForWindow(kInvalidShelfID, window);
}

void ShelfWindowWatcher::OnRootWindowAdded(aura::Window* root_window) {
  // |observed_activation_clients_| can have the same ActivationClient multiple
  // times - which would be handled by the |observed_activation_clients_|.
  observed_activation_clients_.Add(
      aura::client::GetActivationClient(root_window));
  observed_root_windows_.Add(root_window);

  aura::Window* default_container = Shell::GetContainer(
      root_window,
      kShellWindowId_DefaultContainer);
  observed_windows_.Add(default_container);
  for (size_t i = 0; i < default_container->children().size(); ++i)
    observed_windows_.Add(default_container->children()[i]);
}

void ShelfWindowWatcher::OnRootWindowRemoved(aura::Window* root_window) {
  observed_root_windows_.Remove(root_window);
  observed_activation_clients_.Remove(
      aura::client::GetActivationClient(root_window));
}

void ShelfWindowWatcher::UpdateShelfItemStatus(aura::Window* window,
                                               bool is_active) {
  int index = GetShelfItemIndexForWindow(window);
  DCHECK_GE(index, 0);

  ShelfItem item = model_->items()[index];
  item.status = is_active ? STATUS_ACTIVE : STATUS_RUNNING;
  model_->Set(index, item);
}

int ShelfWindowWatcher::GetShelfItemIndexForWindow(
    aura::Window* window) const {
  return model_->ItemIndexByID(GetShelfIDForWindow(window));
}

void ShelfWindowWatcher::StartObservingRemovedWindow(aura::Window* window) {
  observed_removed_windows_.Add(window);
}

void ShelfWindowWatcher::FinishObservingRemovedWindow(aura::Window* window) {
  observed_removed_windows_.Remove(window);
  RemoveShelfItem(window);
}

void ShelfWindowWatcher::OnWindowActivated(aura::Window* gained_active,
                                           aura::Window* lost_active) {
  if (gained_active && HasShelfItemForWindow(gained_active))
    UpdateShelfItemStatus(gained_active, true);
  if (lost_active && HasShelfItemForWindow(lost_active))
    UpdateShelfItemStatus(lost_active, false);
}

void ShelfWindowWatcher::OnWindowAdded(aura::Window* window) {
  observed_windows_.Add(window);

  if (observed_removed_windows_.IsObserving(window)) {
    // When |window| is added and it is already observed by
    // |dragged_window_observer_|, |window| already has its item.
    DCHECK(HasShelfItemForWindow(window));
    observed_removed_windows_.Remove(window);
    return;
  }

  // Add ShelfItem if |window| already has a ShelfItemDetails when it is
  // created. Don't make a new ShelfItem for the re-parented |window| that
  // already has a ShelfItem.
  if (GetShelfIDForWindow(window) == kInvalidShelfID &&
      GetShelfItemDetailsForWindow(window))
    AddShelfItem(window);
}

void ShelfWindowWatcher::OnWillRemoveWindow(aura::Window* window) {
  // Remove a child window of default container.
  if (observed_windows_.IsObserving(window))
    observed_windows_.Remove(window);

  // Don't remove |window| item immediately. Instead, defer handling of removing
  // |window|'s item to RemovedWindowObserver because |window| could be added
  // again to default container.
  if (HasShelfItemForWindow(window))
    StartObservingRemovedWindow(window);
}

void ShelfWindowWatcher::OnWindowDestroying(aura::Window* window) {
  // Remove the default container.
  if (observed_windows_.IsObserving(window))
    observed_windows_.Remove(window);
}

void ShelfWindowWatcher::OnWindowPropertyChanged(aura::Window* window,
                                                 const void* key,
                                                 intptr_t old) {
  if (key != kShelfItemDetailsKey)
    return;

  if (GetShelfItemDetailsForWindow(window) == NULL) {
    // Removes ShelfItem for |window| when it has a ShelfItem.
    if (reinterpret_cast<ShelfItemDetails*>(old) != NULL)
      RemoveShelfItem(window);
    return;
  }

  // When ShelfItemDetails is changed, update ShelfItem.
  if (HasShelfItemForWindow(window)) {
    int index = GetShelfItemIndexForWindow(window);
    DCHECK_GE(index, 0);
    ShelfItem item = model_->items()[index];
    const ShelfItemDetails* details =
        GetShelfItemDetailsForWindow(window);
    SetShelfItemDetailsForShelfItem(&item, *details);
    model_->Set(index, item);
    return;
  }

  // Creates a new ShelfItem for |window|.
  AddShelfItem(window);
}

void ShelfWindowWatcher::OnDisplayAdded(const gfx::Display& new_display) {
  // Add a new RootWindow and its ActivationClient to observed list.
  aura::Window* root_window = Shell::GetInstance()->display_controller()->
      GetRootWindowForDisplayId(new_display.id());

  // When the primary root window's display get removed, the existing root
  // window is taken over by the new display and the observer is already set.
  if (!observed_root_windows_.IsObserving(root_window))
    OnRootWindowAdded(root_window);
}

void ShelfWindowWatcher::OnDisplayRemoved(const gfx::Display& old_display) {
  // When this is called, RootWindow of |old_display| is already removed.
  // Instead, we remove an observer from RootWindow and ActivationClient in the
  // OnRootWindowDestroyed().
  // Do nothing here.
}

void ShelfWindowWatcher::OnDisplayMetricsChanged(const gfx::Display&,
                                                 uint32_t) {
}

}  // namespace ash
