// 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 "chrome/browser/ui/panels/panel_drag_controller.h"

#include "base/logging.h"
#include "chrome/browser/ui/panels/detached_panel_collection.h"
#include "chrome/browser/ui/panels/detached_panel_drag_handler.h"
#include "chrome/browser/ui/panels/docked_panel_collection.h"
#include "chrome/browser/ui/panels/docked_panel_drag_handler.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/stacked_panel_collection.h"
#include "chrome/browser/ui/panels/stacked_panel_drag_handler.h"

namespace {

// The minimum distance that the docked panel gets dragged up in order to
// make it free-floating.
const int kDetachDockedPanelThreshold = 100;

// Indicates how close the bottom of the detached panel is to the bottom of
// the docked area such that the detached panel becomes docked.
const int kDockDetachedPanelThreshold = 30;

// The minimum distance and overlap (in pixels) between two panels such that
// they can be stacked/snapped together.
const int kGluePanelsDistanceThreshold = 15;
const int kGluePanelsOverlapThreshold = 10;

// The minimum distance between the panel edge and the screen (or work area)
// edge such that the panel can snap to the screen (or work area) edge.
const int kSnapPanelToScreenEdgeThreshold = 25;

int GetHorizontalOverlap(const gfx::Rect& bounds1, const gfx::Rect& bounds2) {
  // Check for no overlap.
  if (bounds1.right() <= bounds2.x() || bounds1.x() >= bounds2.right())
    return 0;

  // Check for complete overlap.
  if (bounds2.x() <= bounds1.x() && bounds1.right() <= bounds2.right())
    return bounds1.width();

  if (bounds1.x() <= bounds2.x() && bounds2.right() <= bounds1.right())
    return bounds2.width();

  // Compute the overlap part.
  return (bounds1.x() < bounds2.x()) ? (bounds1.right() - bounds2.x())
                                     : (bounds2.right() - bounds1.x());
}

int GetVerticalOverlap(const gfx::Rect& bounds1, const gfx::Rect& bounds2) {
  // Check for no overlap.
  if (bounds1.bottom() <= bounds2.y() || bounds1.y() >= bounds2.bottom())
    return 0;

  // Check for complete overlap.
  if (bounds2.y() <= bounds1.y() && bounds1.bottom() <= bounds2.bottom())
    return bounds1.height();

  if (bounds1.y() <= bounds2.y() && bounds2.bottom() <= bounds1.bottom())
    return bounds2.height();

  // Compute the overlap part.
  return (bounds1.y() < bounds2.y()) ? (bounds1.bottom() - bounds2.y())
                                     : (bounds2.bottom() - bounds1.y());
}

// Return the vertical distance between the bottom edge of |top_bounds| and
// the top edge of |bottom_bounds|.
int GetVerticalDistance(const gfx::Rect& top_bounds,
                        const gfx::Rect& bottom_bounds) {
  return abs(bottom_bounds.y() - top_bounds.bottom());
}

// Return the vertical distance between the right edge of |left_bounds| and
// the left edge of |right_bounds|.
int GetHorizontalDistance(const gfx::Rect& left_bounds,
                          const gfx::Rect& right_bounds) {
  return abs(right_bounds.x() - left_bounds.right());
}

void SetPreviewModeForPanelAndBelow(Panel* panel, bool in_preview) {
  StackedPanelCollection* stack = panel->stack();
  if (stack) {
    bool panel_found = false;
    for (StackedPanelCollection::Panels::const_iterator iter =
             stack->panels().begin();
         iter != stack->panels().end(); ++iter) {
      Panel* current_panel = *iter;
      if (!panel_found && current_panel != panel)
        continue;
      panel_found = true;
      if (in_preview != current_panel->in_preview_mode())
        current_panel->SetPreviewMode(in_preview);
    }
  } else {
    panel->SetPreviewMode(in_preview);
  }
}

}  // namespace

// static
int PanelDragController::GetDetachDockedPanelThresholdForTesting() {
  return kDetachDockedPanelThreshold;
}

// static
int PanelDragController::GetDockDetachedPanelThresholdForTesting() {
  return kDockDetachedPanelThreshold;
}

// static
int PanelDragController::GetGluePanelDistanceThresholdForTesting() {
  return kGluePanelsDistanceThreshold;
}

// static
int PanelDragController::GetGluePanelOverlapThresholdForTesting() {
  return kGluePanelsOverlapThreshold;
}

// static
int PanelDragController::GetSnapPanelToScreenEdgeThresholdForTesting() {
  return kSnapPanelToScreenEdgeThreshold;
}

PanelDragController::PanelDragController(PanelManager* panel_manager)
    : panel_manager_(panel_manager),
      panel_stacking_enabled_(PanelManager::IsPanelStackingEnabled()),
      dragging_panel_(NULL),
      dragging_panel_original_collection_(NULL) {
}

PanelDragController::~PanelDragController() {
}

void PanelDragController::StartDragging(Panel* panel,
                                        const gfx::Point& mouse_location) {
  DCHECK(!dragging_panel_);

  offset_from_mouse_location_on_drag_start_ =
      mouse_location - panel->GetBounds().origin();

  dragging_panel_ = panel;
  SetPreviewModeForPanelAndBelow(dragging_panel_, true);

  // Keep track of original collection and placement for the case that the drag
  // is cancelled.
  dragging_panel_original_collection_ = dragging_panel_->collection();
  dragging_panel_original_collection_->SavePanelPlacement(dragging_panel_);
}

void PanelDragController::Drag(const gfx::Point& mouse_location) {
  if (!dragging_panel_)
    return;

  gfx::Point target_position = GetPanelPositionForMouseLocation(mouse_location);

  if (panel_stacking_enabled_) {
    // Check if the dragging panel can be moved out the stack. Note that this
    // has to be done first and we should continue processing it for the case
    // that the drag also triggers stacking and docking.
    // Note that the panel can only be unstacked from top or bottom. So if
    // unstacking from top succeeds, there is no need to check for unstacking
    // from bottom.
    if (!TryUnstackFromTop(target_position))
      TryUnstackFromBottom(target_position);

    // Check if the dragging panel can stack with other panel or stack.
    TryStack(target_position);
  }

  // Check if the dragging panel can be docked.
  TryDock(target_position);

  // Check if the dragging panel can be detached.
  TryDetach(target_position);

  // Check if the dragging panel can snap to other panel or edge of the working
  // area.
  if (panel_stacking_enabled_)
    TrySnap(&target_position);

  // At last, handle the drag via its collection's specific handler.
  switch (dragging_panel_->collection()->type()) {
    case PanelCollection::DOCKED:
      DockedPanelDragHandler::HandleDrag(dragging_panel_, target_position);
      break;
    case PanelCollection::DETACHED:
      DetachedPanelDragHandler::HandleDrag(dragging_panel_, target_position);
      break;
    case PanelCollection::STACKED:
      StackedPanelDragHandler::HandleDrag(
          dragging_panel_,
          target_position,
          dragging_panel_->collection() == dragging_panel_original_collection_);
      break;
    default:
      NOTREACHED();
      break;
  }
}

void PanelDragController::EndDragging(bool cancelled) {
  if (!dragging_panel_)
    return;

  PanelCollection* current_collection = dragging_panel_->collection();
  if (cancelled) {
    // Restore the dragging panel to its original collection if needed.
    // Note that the bounds of dragging panel is updated later by calling
    // RestorePanelToSavedPlacement.
    if (current_collection != dragging_panel_original_collection_) {
      PanelCollection::PositioningMask positioning_mask =
          static_cast<PanelCollection::PositioningMask>(
              PanelCollection::DEFAULT_POSITION |
              PanelCollection::DO_NOT_UPDATE_BOUNDS);
      MovePanelAndBelowToCollection(dragging_panel_,
                                    dragging_panel_original_collection_,
                                    positioning_mask);
    }

    // End the preview mode.
    SetPreviewModeForPanelAndBelow(dragging_panel_, false);

    // Restore the dragging panel to its original placement.
    dragging_panel_original_collection_->RestorePanelToSavedPlacement();
  } else {
    // The saved placement is no longer needed.
    dragging_panel_original_collection_->DiscardSavedPanelPlacement();

    // Finalizing the drag.
    if (current_collection->type() == PanelCollection::STACKED)
      StackedPanelDragHandler::FinalizeDrag(dragging_panel_);

    // End the preview mode.
    SetPreviewModeForPanelAndBelow(dragging_panel_, false);

    // This could cause the panel to be moved to its finalized position.
    current_collection->RefreshLayout();

    // This could cause the detached panel, that still keeps its minimized state
    // when it gets detached due to unstacking, to expand. This could occur
    // when the stack has more than 2 panels and the 2nd top panel is unstacked
    // from the top panel: the top panel is detached while all other panels
    // remain in the stack.
    if (current_collection != panel_manager_->detached_collection())
      panel_manager_->detached_collection()->RefreshLayout();
  }

  // If the origianl collection is a stack and it becomes empty, remove it.
  if (dragging_panel_original_collection_->type() == PanelCollection::STACKED) {
    StackedPanelCollection* original_stack =
        static_cast<StackedPanelCollection*>(
            dragging_panel_original_collection_);
    if (original_stack->num_panels() == 0)
      panel_manager_->RemoveStack(original_stack);
  }

  dragging_panel_ = NULL;
}

void PanelDragController::OnPanelClosed(Panel* panel) {
  // Abort the drag only if the panel being closed is currently being dragged.
  if (dragging_panel_ != panel)
    return;

  dragging_panel_original_collection_->DiscardSavedPanelPlacement();
  dragging_panel_original_collection_ = NULL;
  dragging_panel_ = NULL;
}

gfx::Point PanelDragController::GetPanelPositionForMouseLocation(
    const gfx::Point& mouse_location) const {
  // The target panel position is computed based on the fact that the panel
  // should follow the mouse movement.
  gfx::Point target_position =
      mouse_location - offset_from_mouse_location_on_drag_start_;
  gfx::Rect target_bounds(target_position, dragging_panel_->GetBounds().size());

  // Make sure that the panel's titlebar cannot be moved under the taskbar or
  // OSX menu bar that is aligned to top screen edge.
  gfx::Rect display_area = panel_manager_->display_settings_provider()->
      GetDisplayAreaMatching(target_bounds);
  gfx::Rect work_area = panel_manager_->display_settings_provider()->
      GetWorkAreaMatching(target_bounds);
  if (display_area.Contains(mouse_location) &&
      target_position.y() < work_area.y()) {
    target_position.set_y(work_area.y());
  }

  return target_position;
}

void PanelDragController::TryDetach(const gfx::Point& target_position) {
  // It has to come from the docked collection.
  if (dragging_panel_->collection()->type() != PanelCollection::DOCKED)
    return;

  // The minimized docked panel is not allowed to detach.
  if (dragging_panel_->IsMinimized())
    return;

  // Panels in the detached collection are always at their full size.
  gfx::Rect target_bounds(target_position, dragging_panel_->full_size());

  // To become detached, the panel should be dragged either out of the main
  // work area or up high enough to pass certain threshold.
  gfx::Rect target_work_area = panel_manager_->display_settings_provider()->
      GetWorkAreaMatching(target_bounds);
  gfx::Rect dock_work_area = panel_manager_->docked_collection()->work_area();
  if (target_work_area.Contains(dock_work_area) &&
      dock_work_area.bottom() - target_bounds.bottom() <
          kDetachDockedPanelThreshold) {
    return;
  }

  // Apply new panel bounds.
  dragging_panel_->SetPanelBoundsInstantly(target_bounds);

  // Move the panel to new collection.
  panel_manager_->MovePanelToCollection(dragging_panel_,
                                        panel_manager_->detached_collection(),
                                        PanelCollection::KNOWN_POSITION);
}

void PanelDragController::TryDock(const gfx::Point& target_position) {
  // It has to come from the detached collection.
  if (dragging_panel_->collection()->type() != PanelCollection::DETACHED)
    return;

  gfx::Rect target_bounds(target_position, dragging_panel_->GetBounds().size());

  // To become docked, the panel should fall within the main work area and
  // its bottom should come very close to or fall below the bottom of the main
  // work area.
  gfx::Rect target_work_area = panel_manager_->display_settings_provider()->
      GetWorkAreaMatching(target_bounds);
  gfx::Rect dock_work_area = panel_manager_->docked_collection()->work_area();
  if (!target_work_area.Contains(dock_work_area) ||
      dock_work_area.bottom() - target_bounds.bottom() >
          kDockDetachedPanelThreshold) {
    return;
  }

  // Apply new panel bounds.
  dragging_panel_->SetPanelBoundsInstantly(target_bounds);

  // Move the panel to new collection.
  panel_manager_->MovePanelToCollection(dragging_panel_,
                                        panel_manager_->docked_collection(),
                                        PanelCollection::KNOWN_POSITION);
}

void PanelDragController::TryStack(const gfx::Point& target_position) {
  gfx::Rect target_bounds;
  GlueEdge target_edge;
  Panel* target_panel = FindPanelToGlue(target_position,
                                        STACK,
                                        &target_bounds,
                                        &target_edge);
  if (!target_panel)
    return;

  StackedPanelCollection* dragging_stack = dragging_panel_->stack();

  // Move the panel (and all the panels below if in a stack) to the new
  // position.
  gfx::Vector2d delta =
      target_bounds.origin() - dragging_panel_->GetBounds().origin();
  if (dragging_stack)
    dragging_stack->MoveAllDraggingPanelsInstantly(delta);
  else
    dragging_panel_->MoveByInstantly(delta);

  // If the panel to stack with is not in a stack, create it now.
  StackedPanelCollection* target_stack = target_panel->stack();
  if (!target_stack) {
    target_stack = panel_manager_->CreateStack();
    panel_manager_->MovePanelToCollection(target_panel,
                                          target_stack,
                                          PanelCollection::DEFAULT_POSITION);
  }

  // Move the panel to new collection.
  // Note that we don't want to refresh the layout now because when we add
  // a panel to top of other panel, we don't want the bottom panel to change
  // its width to be same as top panel now.
  PanelCollection::PositioningMask positioning_mask =
      static_cast<PanelCollection::PositioningMask>(
          PanelCollection::NO_LAYOUT_REFRESH |
          (target_edge == TOP_EDGE ? PanelCollection::TOP_POSITION
                                   : PanelCollection::DEFAULT_POSITION));
  MovePanelAndBelowToCollection(dragging_panel_,
                                target_stack,
                                positioning_mask);
}

// Check if a panel or a set of stacked panels (being dragged together from a
// stack) can be dragged away from the panel below such that the former panel(s)
// are not in the same stack as the latter panel.
bool PanelDragController::TryUnstackFromTop(const gfx::Point& target_position) {
  // It has to be stacked.
  StackedPanelCollection* dragging_stack = dragging_panel_->stack();
  if (!dragging_stack)
    return false;

  // Unstacking from top only happens when a panel/stack stacks to the top of
  // another panel and then moves away while the drag is still in progress.
  if (dragging_panel_ != dragging_stack->top_panel() ||
      dragging_stack == dragging_panel_original_collection_)
    return false;

  // Count the number of panels that might need to unstack.
  Panel* last_panel_to_unstack = NULL;
  Panel* panel_below_last_panel_to_unstack = NULL;
  int num_panels_to_unstack = 0;
  for (StackedPanelCollection::Panels::const_iterator iter =
           dragging_stack->panels().begin();
       iter != dragging_stack->panels().end(); ++iter) {
    if (!(*iter)->in_preview_mode()) {
      panel_below_last_panel_to_unstack = *iter;
      break;
    }
    num_panels_to_unstack++;
    last_panel_to_unstack = *iter;
  }
  DCHECK_GE(num_panels_to_unstack, 1);
  if (num_panels_to_unstack == dragging_stack->num_panels())
    return false;

  gfx::Vector2d delta = target_position - dragging_panel_->GetBounds().origin();

  // The last panel to unstack should be dragged far enough from its below
  // panel.
  gfx::Rect target_bounds = last_panel_to_unstack->GetBounds();
  target_bounds.Offset(delta);
  gfx::Rect below_panel_bounds = panel_below_last_panel_to_unstack->GetBounds();
  if (GetVerticalDistance(target_bounds, below_panel_bounds) <
          kGluePanelsDistanceThreshold &&
      GetHorizontalOverlap(target_bounds, below_panel_bounds) >
          kGluePanelsOverlapThreshold) {
    return false;
  }

  int num_panels_in_stack = dragging_stack->num_panels();
  DCHECK_GE(num_panels_in_stack, 2);

  // When a panel is removed from its stack, we always make it detached. If it
  // indeed should go to the docked collection, the subsequent TryDock will then
  // move it from the detached collection to the docked collection.
  DetachedPanelCollection* detached_collection =
      panel_manager_->detached_collection();

  // If there're only 2 panels in the stack, both panels should move out of the
  // stack and the stack should be removed.
  if (num_panels_in_stack == 2) {
    DCHECK_EQ(1, num_panels_to_unstack);
    MovePanelAndBelowToCollection(dragging_panel_,
                                  detached_collection,
                                  PanelCollection::KNOWN_POSITION);
    dragging_panel_->MoveByInstantly(delta);
    return true;
  }

  DCHECK_GE(num_panels_in_stack, 3);

  // If only one panel (top panel) needs to unstack, move it out of the stack.
  if (num_panels_to_unstack == 1) {
    panel_manager_->MovePanelToCollection(dragging_panel_,
                                          detached_collection,
                                          PanelCollection::KNOWN_POSITION);
    dragging_panel_->MoveByInstantly(delta);
    return true;
  }

  // If all the panels except the bottom panel need to unstack, simply move
  // bottom panel out of the stack.
  if (num_panels_in_stack - num_panels_to_unstack == 1) {
    panel_manager_->MovePanelToCollection(dragging_stack->bottom_panel(),
                                          detached_collection,
                                          PanelCollection::KNOWN_POSITION);
    dragging_panel_->stack()->MoveAllDraggingPanelsInstantly(delta);
    return true;
  }

  // Otherwise, move all unstacked panels to a new stack.
  // Note that all the panels to move should be copied to a local list first
  // because the stack collection will be modified during the move.
  std::list<Panel*> panels_to_move;
  for (StackedPanelCollection::Panels::const_iterator iter =
           dragging_stack->panels().begin();
       iter != dragging_stack->panels().end(); ++iter) {
    Panel* panel = *iter;
    if (!panel->in_preview_mode())
      break;
    panels_to_move.push_back(panel);
  }
  StackedPanelCollection* new_stack = panel_manager_->CreateStack();
  for (std::list<Panel*>::const_iterator iter = panels_to_move.begin();
       iter != panels_to_move.end(); ++iter) {
    panel_manager_->MovePanelToCollection(*iter,
                                          new_stack,
                                          PanelCollection::KNOWN_POSITION);
  }
  dragging_panel_->stack()->MoveAllDraggingPanelsInstantly(delta);

  return true;
}

// Check if a panel or a set of stacked panels (being dragged together from a
// stack) can be dragged away from the panel above such that the former panel(s)
// are not in the same stack as the latter panel.
bool PanelDragController::TryUnstackFromBottom(
    const gfx::Point& target_position) {
  // It has to be stacked.
  StackedPanelCollection* dragging_stack = dragging_panel_->stack();
  if (!dragging_stack)
    return false;

  // It cannot be the top panel.
  if (dragging_panel_ == dragging_stack->top_panel())
    return false;

  DCHECK_GT(dragging_stack->num_panels(), 1);

  gfx::Rect target_bounds(target_position, dragging_panel_->GetBounds().size());

  // The panel should be dragged far enough from its above panel.
  Panel* above_panel = dragging_stack->GetPanelAbove(dragging_panel_);
  DCHECK(above_panel);
  gfx::Rect above_panel_bounds = above_panel->GetBounds();
  if (GetVerticalDistance(above_panel_bounds, target_bounds) <
          kGluePanelsDistanceThreshold &&
      GetHorizontalOverlap(above_panel_bounds, target_bounds) >
          kGluePanelsOverlapThreshold) {
    return false;
  }

  gfx::Vector2d delta = target_position - dragging_panel_->GetBounds().origin();

  // If there're only 2 panels in the stack, both panels should move out the
  // stack and the stack should be removed.
  DetachedPanelCollection* detached_collection =
      panel_manager_->detached_collection();
  if (dragging_stack->num_panels() == 2) {
    MovePanelAndBelowToCollection(dragging_stack->top_panel(),
                                  detached_collection,
                                  PanelCollection::KNOWN_POSITION);
    dragging_panel_->MoveByInstantly(delta);
    return true;
  }

  // There're at least 3 panels.
  DCHECK_GE(dragging_stack->num_panels(), 3);

  // If the dragging panel is bottom panel, move it out of the stack.
  if (dragging_panel_ == dragging_stack->bottom_panel()) {
    panel_manager_->MovePanelToCollection(dragging_panel_,
                                          detached_collection,
                                          PanelCollection::KNOWN_POSITION);
    dragging_panel_->MoveByInstantly(delta);
    return true;
  }

  // If the dragging panel is the one below the top panel, move top panel
  // out of the stack.
  if (dragging_stack->GetPanelAbove(dragging_panel_) ==
      dragging_stack->top_panel()) {
    panel_manager_->MovePanelToCollection(dragging_stack->top_panel(),
                                          detached_collection,
                                          PanelCollection::KNOWN_POSITION);
    dragging_panel_->stack()->MoveAllDraggingPanelsInstantly(delta);
    return true;
  }

  // There're at least 4 panels.
  DCHECK_GE(dragging_stack->num_panels(), 4);

  // We can split them into 2 stacks by moving the dragging panel and all panels
  // below to a new stack while keeping all panels above in the same stack.
  StackedPanelCollection* new_stack = panel_manager_->CreateStack();
  MovePanelAndBelowToCollection(dragging_panel_,
                                new_stack,
                                PanelCollection::KNOWN_POSITION);
  dragging_panel_->stack()->MoveAllDraggingPanelsInstantly(delta);

  return true;
}

void PanelDragController::TrySnap(gfx::Point* target_position) {
  // Snapping does not apply to docked panels.
  if (dragging_panel_->collection()->type() == PanelCollection::DOCKED)
    return;

  // Check if the panel can snap to other panel.
  gfx::Rect target_bounds;
  GlueEdge target_edge;
  Panel* target_panel = FindPanelToGlue(*target_position,
                                        SNAP,
                                        &target_bounds,
                                        &target_edge);
  if (target_panel) {
    *target_position = target_bounds.origin();
    return;
  }

  // Check if the panel can snap to the left/right edge of the work area.
  target_bounds.set_origin(*target_position);
  target_bounds.set_size(dragging_panel_->GetBounds().size());
  gfx::Rect work_area = panel_manager_->display_settings_provider()->
      GetWorkAreaMatching(target_bounds);
  if (abs(target_position->x() - work_area.x()) <
      kSnapPanelToScreenEdgeThreshold) {
    target_position->set_x(work_area.x());
  } else {
    int width = dragging_panel_->GetBounds().width();
    if (abs(work_area.right() - target_position->x() - width) <
        kSnapPanelToScreenEdgeThreshold)
      target_position->set_x(work_area.right() - width);
  }

  // Check if the panel can snap to the top/bottom edge of the work area.
  if (abs(target_position->y() - work_area.y()) <
      kSnapPanelToScreenEdgeThreshold) {
    target_position->set_y(work_area.y());
  } else {
    // If the panel is in a stack, the height is from the top edge of this panel
    // to the bottom edge of the last panel in the stack.
    int height;
    StackedPanelCollection* stack = dragging_panel_->stack();
    if (stack) {
      height = stack->bottom_panel()->GetBounds().bottom() -
          dragging_panel_->GetBounds().y();
    } else {
      height = dragging_panel_->GetBounds().height();
    }
    if (abs(work_area.bottom() - target_position->y() - height) <
        kSnapPanelToScreenEdgeThreshold)
      target_position->set_y(work_area.bottom() - height);
  }
}

Panel* PanelDragController::FindPanelToGlue(
    const gfx::Point& potential_position,
    GlueAction action,
    gfx::Rect* target_bounds,
    GlueEdge* target_edge) const {
  int best_distance = kint32max;
  Panel* best_matching_panel = NULL;

  // Compute the potential bounds for the dragging panel.
  gfx::Rect current_dragging_bounds = dragging_panel_->GetBounds();
  gfx::Rect potential_dragging_bounds(potential_position,
                                      current_dragging_bounds.size());

  // Compute the potential bounds for the bottom panel if the dragging panel is
  // in a stack. If not, it is same as |potential_dragging_bounds|.
  // This is used to determine if the dragging panel or the bottom panel can
  // stack to the top of other panel.
  gfx::Rect current_bottom_bounds;
  gfx::Rect potential_bottom_bounds;
  StackedPanelCollection* dragging_stack = dragging_panel_->stack();
  if (dragging_stack && dragging_panel_ != dragging_stack->bottom_panel()) {
    gfx::Vector2d delta = potential_position - current_dragging_bounds.origin();
    current_bottom_bounds = dragging_stack->bottom_panel()->GetBounds();
    potential_bottom_bounds = current_bottom_bounds;
    potential_bottom_bounds.Offset(delta);
  } else {
    current_bottom_bounds = current_dragging_bounds;
    potential_bottom_bounds = potential_dragging_bounds;
  }

  // Go through all non-docked panels.
  std::vector<Panel*> panels = panel_manager_->GetDetachedAndStackedPanels();
  for (std::vector<Panel*>::const_iterator iter = panels.begin();
       iter != panels.end(); ++iter) {
    Panel* panel = *iter;
    if (dragging_panel_ == panel)
      continue;
    if (dragging_panel_->collection()->type() == PanelCollection::STACKED &&
        dragging_panel_->collection() == panel->collection())
      continue;
    gfx::Rect panel_bounds = panel->GetBounds();
    int distance;
    int overlap;

    if (action == SNAP) {
      overlap = GetVerticalOverlap(potential_dragging_bounds, panel_bounds);
      if (overlap > kGluePanelsOverlapThreshold) {
        // Can |dragging_panel_| snap to left edge of |panel|?
        distance = GetHorizontalDistance(potential_dragging_bounds,
                                         panel_bounds);
        if (distance < kGluePanelsDistanceThreshold &&
            distance < best_distance) {
          best_distance = distance;
          best_matching_panel = panel;
          *target_edge = LEFT_EDGE;
          *target_bounds = potential_dragging_bounds;
          target_bounds->set_x(panel_bounds.x() - target_bounds->width());
        }

        // Can |dragging_panel_| snap to right edge of |panel|?
        distance = GetHorizontalDistance(panel_bounds,
                                         potential_dragging_bounds);
        if (distance < kGluePanelsDistanceThreshold &&
            distance < best_distance) {
          best_distance = distance;
          best_matching_panel = panel;
          *target_edge = RIGHT_EDGE;
          *target_bounds = potential_dragging_bounds;
          target_bounds->set_x(panel_bounds.right());
        }
      }
    } else {
      DCHECK_EQ(STACK, action);
      StackedPanelCollection* stack = panel->stack();

      // Can |dragging_panel_| or the bottom panel in |dragging_panel_|'s stack
      // stack to top edge of |panel|? If |panel| is in a stack and not top
      // panel, its top edge is interior edge and thus cannot be aligned with.
      distance = GetVerticalDistance(potential_bottom_bounds, panel_bounds);
      overlap = GetHorizontalOverlap(panel_bounds, potential_bottom_bounds);
      if ((!stack || panel == stack->top_panel()) &&
          distance < kGluePanelsDistanceThreshold &&
          overlap > kGluePanelsOverlapThreshold &&
          distance < best_distance) {
        best_distance = distance;
        best_matching_panel = panel;
        *target_edge = TOP_EDGE;
        target_bounds->SetRect(
            potential_dragging_bounds.x(),
            current_dragging_bounds.y() + panel_bounds.y() -
                current_bottom_bounds.height() - current_bottom_bounds.y(),
            potential_dragging_bounds.width(),
            potential_dragging_bounds.height());
      }

      // Can |dragging_panel_| stack to bottom edge of |panel|? If |panel| is
      // in a stack and not bottom panel, its bottom edge is interior edge and
      // thus cannot be aligned with.
      distance = GetVerticalDistance(panel_bounds, potential_dragging_bounds);
      overlap = GetHorizontalOverlap(panel_bounds, potential_dragging_bounds);
      if ((!stack || panel == stack->bottom_panel()) &&
          distance < kGluePanelsDistanceThreshold &&
          overlap > kGluePanelsOverlapThreshold &&
          distance < best_distance) {
        best_distance = distance;
        best_matching_panel = panel;
        *target_edge = BOTTOM_EDGE;
        target_bounds->SetRect(potential_dragging_bounds.x(),
                               panel_bounds.bottom(),
                               potential_dragging_bounds.width(),
                               potential_dragging_bounds.height());
      }
    }
  }

  return best_matching_panel;
}

void PanelDragController::MovePanelAndBelowToCollection(
    Panel* panel,
    PanelCollection* target_collection,
    PanelCollection::PositioningMask positioning_mask) const {
  StackedPanelCollection* stack = panel->stack();
  if (!stack) {
    panel_manager_->MovePanelToCollection(panel,
                                          target_collection,
                                          positioning_mask);
    return;
  }

  // Note that all the panels to move should be copied to a local list first
  // because the stack collection will be modified during the move.
  std::list<Panel*> panels_to_move;
  StackedPanelCollection::Panels::const_iterator iter = stack->panels().begin();
  for (; iter != stack->panels().end(); ++iter)
    if ((*iter) == panel)
      break;
  for (; iter != stack->panels().end(); ++iter) {
    // Note that if the panels are going to be inserted from the top, we need
    // to reverse the order when copying to the local list.
    if (positioning_mask & PanelCollection::TOP_POSITION)
      panels_to_move.push_front(*iter);
    else
      panels_to_move.push_back(*iter);
  }
  for (std::list<Panel*>::const_iterator panel_iter = panels_to_move.begin();
       panel_iter != panels_to_move.end(); ++panel_iter) {
    panel_manager_->MovePanelToCollection(*panel_iter,
                                          target_collection,
                                          positioning_mask);
  }

  // If the stack becomes empty or has only one panel left, no need to keep
  // the stack.
  if (stack && stack->num_panels() <= 1) {
    if (stack->num_panels() == 1) {
      panel_manager_->MovePanelToCollection(
          stack->top_panel(),
          panel_manager_->detached_collection(),
          PanelCollection::KNOWN_POSITION);
    }
    // Note that if the stack is the original collection, do not remove it now.
    // This is because the original collection contains the information to
    // restore the dragging panel to the right place when the drag is cancelled.
    if (stack != dragging_panel_original_collection_)
      panel_manager_->RemoveStack(stack);
  }
}
