// Copyright 2016 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 "ui/display/display_layout.h"

#include <algorithm>
#include <map>
#include <set>
#include <sstream>
#include <unordered_map>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"

namespace display {
namespace {

// DisplayPlacement Positions
const char kTop[] = "top";
const char kRight[] = "right";
const char kBottom[] = "bottom";
const char kLeft[] = "left";
const char kUnknown[] = "unknown";

// The maximum value for 'offset' in DisplayLayout in case of outliers.  Need
// to change this value in case to support even larger displays.
const int kMaxValidOffset = 10000;

bool IsIdInList(int64_t id, const DisplayIdList& list) {
  const auto iter =
      std::find_if(list.begin(), list.end(),
                   [id](int64_t display_id) { return display_id == id; });
  return iter != list.end();
}

bool ComparePlacements(const DisplayPlacement& d1, const DisplayPlacement& d2) {
  return CompareDisplayIds(d1.display_id, d2.display_id);
}

// Extracts the displays IDs list from the displays list.
DisplayIdList DisplayListToDisplayIdList(const Displays& displays) {
  DisplayIdList list;
  for (const auto& display : displays)
    list.emplace_back(display.id());

  return list;
}

// Ruturns nullptr if display with |id| is not found.
Display* FindDisplayById(Displays* display_list, int64_t id) {
  auto iter =
      std::find_if(display_list->begin(), display_list->end(),
                   [id](const Display& display) { return display.id() == id; });
  return iter == display_list->end() ? nullptr : &(*iter);
}

// Returns the tree depth of the display with ID |display_id| from the tree root
// (i.e. from the primary display).
int GetDisplayTreeDepth(
    int64_t display_id,
    int64_t primary_id,
    const std::map<int64_t, int64_t>& display_to_parent_ids_map) {
  int64_t current_id = display_id;
  int depth = 0;
  const int kMaxDepth = 100;  // Avoid layouts with cycles.
  while (current_id != primary_id && depth < kMaxDepth) {
    ++depth;
    auto iter = display_to_parent_ids_map.find(current_id);
    if (iter == display_to_parent_ids_map.end())
      return kMaxDepth;  // Let detached diplays go to the end.

    current_id = iter->second;
  }

  return depth;
}

// Returns true if the child and parent displays are sharing a border that
// matches the child's relative position to its parent.
bool AreDisplaysTouching(const Display& child_display,
                         const Display& parent_display,
                         DisplayPlacement::Position child_position) {
  const gfx::Rect& a_bounds = child_display.bounds();
  const gfx::Rect& b_bounds = parent_display.bounds();

  if (child_position == DisplayPlacement::TOP ||
      child_position == DisplayPlacement::BOTTOM) {
    const int rb = std::min(a_bounds.bottom(), b_bounds.bottom());
    const int ry = std::max(a_bounds.y(), b_bounds.y());
    return rb == ry;
  }

  const int rx = std::max(a_bounds.x(), b_bounds.x());
  const int rr = std::min(a_bounds.right(), b_bounds.right());
  return rr == rx;
}

// After the layout has been applied to the |display_list| and any possible
// overlaps have been fixed, this function is called to update the offsets in
// the |placement_list|, and make sure the placement list is sorted by display
// IDs.
void UpdatePlacementList(Displays* display_list,
                         std::vector<DisplayPlacement>* placement_list) {
  std::sort(placement_list->begin(), placement_list->end(), ComparePlacements);

  for (DisplayPlacement& placement : *placement_list) {
    const Display* child_display =
        FindDisplayById(display_list, placement.display_id);
    const Display* parent_display =
        FindDisplayById(display_list, placement.parent_display_id);

    if (!child_display || !parent_display)
      continue;

    const gfx::Rect& child_bounds = child_display->bounds();
    const gfx::Rect& parent_bounds = parent_display->bounds();

    if (placement.position == DisplayPlacement::TOP ||
        placement.position == DisplayPlacement::BOTTOM) {
      placement.offset = child_bounds.x() - parent_bounds.x();
    } else {
      placement.offset = child_bounds.y() - parent_bounds.y();
    }
  }
}

// Reparents |target_display| to |last_intersecting_source_display| if it's not
// touching with its current parent. It also handles the case if
// |target_display| is detached, it then reparents it to the last intersecting
// display.
void MaybeReparentTargetDisplay(
    int last_offset_x,
    int last_offset_y,
    const Display* last_intersecting_source_display,
    const Display* target_display,
    std::map<int64_t, int64_t>* display_to_parent_ids_map,
    Displays* display_list,
    std::vector<DisplayPlacement>* placement_list) {
  // A de-intersection was performed.
  // The offset target display may have moved such that it no longer touches
  // its parent. Reparent if necessary.
  DisplayPlacement* target_display_placement = nullptr;
  auto iter = display_to_parent_ids_map->find(target_display->id());
  if (iter != display_to_parent_ids_map->end()) {
    const int64_t parent_display_id = iter->second;
    if (parent_display_id == last_intersecting_source_display->id()) {
      // It was just de-intersected with the source display in such a way that
      // they're touching, and the source display is its parent. So no need to
      // do any reparenting.
      return;
    }

    Display* parent_display = FindDisplayById(display_list, parent_display_id);
    DCHECK(parent_display);

    auto target_display_placement_itr =
        std::find_if(placement_list->begin(), placement_list->end(),
                     [&target_display](const DisplayPlacement& p) {
                       return p.display_id == target_display->id();
                     });
    DCHECK(target_display_placement_itr != placement_list->end());
    target_display_placement = &(*target_display_placement_itr);
    if (AreDisplaysTouching(*target_display, *parent_display,
                            target_display_placement->position)) {
      return;
    }
  } else {
    // It's a detached display with no parent. Add a new placement for it.
    DisplayPlacement new_placement;
    new_placement.display_id = target_display->id();
    placement_list->emplace_back(new_placement);
    target_display_placement = &placement_list->back();
  }

  DCHECK(target_display_placement);

  // Reparent the target to source and update the position. No need to
  // update the offset here as it will be done later when UpdateOffsets()
  // is called.
  target_display_placement->parent_display_id =
      last_intersecting_source_display->id();
  // Update the map.
  (*display_to_parent_ids_map)[target_display->id()] =
      last_intersecting_source_display->id();

  if (last_offset_x) {
    target_display_placement->position =
        last_offset_x > 0 ? DisplayPlacement::RIGHT : DisplayPlacement::LEFT;
  } else {
    target_display_placement->position =
        last_offset_y > 0 ? DisplayPlacement::BOTTOM : DisplayPlacement::TOP;
  }
}

// Offsets |display| by the provided |x| and |y| values.
void OffsetDisplay(Display* display, int x, int y) {
  gfx::Point new_origin = display->bounds().origin();
  new_origin.Offset(x, y);
  gfx::Insets insets = display->GetWorkAreaInsets();
  display->set_bounds(gfx::Rect(new_origin, display->bounds().size()));
  display->UpdateWorkAreaFromInsets(insets);
}

// Calculates the amount of offset along the X or Y axes for the target display
// with |target_bounds| to de-intersect with the source display with
// |source_bounds|.
// These functions assume both displays already intersect.
int CalculateOffsetX(const gfx::Rect& source_bounds,
                     const gfx::Rect& target_bounds) {
  if (target_bounds.x() >= 0) {
    // Target display moves along the +ve X direction.
    return source_bounds.right() - target_bounds.x();
  }

  // Target display moves along the -ve X direction.
  return -(target_bounds.right() - source_bounds.x());
}
int CalculateOffsetY(const gfx::Rect& source_bounds,
                     const gfx::Rect& target_bounds) {
  if (target_bounds.y() >= 0) {
    // Target display moves along the +ve Y direction.
    return source_bounds.bottom() - target_bounds.y();
  }

  // Target display moves along the -ve Y direction.
  return -(target_bounds.bottom() - source_bounds.y());
}

// Fixes any overlapping displays and reparents displays if necessary.
void DeIntersectDisplays(int64_t primary_id,
                         Displays* display_list,
                         std::vector<DisplayPlacement>* placement_list,
                         std::set<int64_t>* updated_displays) {
  std::map<int64_t, int64_t> display_to_parent_ids_map;
  for (const DisplayPlacement& placement : *placement_list) {
    display_to_parent_ids_map.insert(
        std::make_pair(placement.display_id, placement.parent_display_id));
  }

  std::vector<Display*> sorted_displays;
  for (Display& display : *display_list)
    sorted_displays.push_back(&display);

  // Sort the displays first by their depth in the display hierarchy tree, and
  // then by distance of their top left points from the origin. This way we
  // process the displays starting at the root (the primary display), in the
  // order of their decendence spanning out from the primary display.
  std::sort(sorted_displays.begin(), sorted_displays.end(), [&](Display* d1,
                                                                Display* d2) {
    const int d1_depth =
        GetDisplayTreeDepth(d1->id(), primary_id, display_to_parent_ids_map);
    const int d2_depth =
        GetDisplayTreeDepth(d2->id(), primary_id, display_to_parent_ids_map);

    if (d1_depth != d2_depth)
      return d1_depth < d2_depth;

    const int64_t d1_distance = d1->bounds().OffsetFromOrigin().LengthSquared();
    const int64_t d2_distance = d2->bounds().OffsetFromOrigin().LengthSquared();

    if (d1_distance != d2_distance)
      return d1_distance < d2_distance;

    return d1->id() < d2->id();
  });
  // This must result in the primary display being at the front of the list.
  DCHECK_EQ(sorted_displays.front()->id(), primary_id);

  for (size_t i = 1; i < sorted_displays.size(); ++i) {
    Display* target_display = sorted_displays[i];
    const Display* last_intersecting_source_display = nullptr;
    int last_offset_x = 0;
    int last_offset_y = 0;
    for (size_t j = 0; j < i; ++j) {
      const Display* source_display = sorted_displays[j];
      const gfx::Rect source_bounds = source_display->bounds();
      const gfx::Rect target_bounds = target_display->bounds();

      gfx::Rect intersection = source_bounds;
      intersection.Intersect(target_bounds);

      if (intersection.IsEmpty())
        continue;

      // Calculate offsets along both X and Y axes such that either can remove
      // the overlap, but choose and apply the smaller offset. This way we have
      // more predictable results.
      int offset_x = 0;
      int offset_y = 0;
      if (intersection.width())
        offset_x = CalculateOffsetX(source_bounds, target_bounds);
      if (intersection.height())
        offset_y = CalculateOffsetY(source_bounds, target_bounds);

      if (offset_x == 0 && offset_y == 0)
        continue;

      // Choose the smaller offset.
      if (std::abs(offset_x) <= std::abs(offset_y))
        offset_y = 0;
      else
        offset_x = 0;

      OffsetDisplay(target_display, offset_x, offset_y);
      updated_displays->insert(target_display->id());

      // The most recent performed de-intersection data.
      last_intersecting_source_display = source_display;
      last_offset_x = offset_x;
      last_offset_y = offset_y;
    }

    if (!last_intersecting_source_display)
      continue;

    MaybeReparentTargetDisplay(last_offset_x, last_offset_y,
                               last_intersecting_source_display, target_display,
                               &display_to_parent_ids_map, display_list,
                               placement_list);
  }

  // New placements might have been added and offsets might have changed and we
  // must update them.
  UpdatePlacementList(display_list, placement_list);
}

// Checks if the given point is over the radius vector described by its end
// point |vector|. The point is over a vector if it's on its positive (left)
// side. The method sees a point on the same line as the vector as being over
// the vector.
bool IsPointOverRadiusVector(const gfx::Point& point,
                             const gfx::Point& vector) {
  // |point| is left of |vector| if its radius vector's scalar product with a
  // vector orthogonal (and facing the positive side) to |vector| is positive.
  //
  // An orthogonal vector of (a, b) is (b, -a), as the scalar product of these
  // two is 0.
  // So, (x, y) is over (a, b) if x * b + y * (-a) >= 0, which is equivalent to
  // x * b >= y * a.
  return static_cast<int64_t>(point.x()) * static_cast<int64_t>(vector.y()) >=
         static_cast<int64_t>(point.y()) * static_cast<int64_t>(vector.x());
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// DisplayPlacement

DisplayPlacement::DisplayPlacement()
    : DisplayPlacement(kInvalidDisplayId,
                       kInvalidDisplayId,
                       DisplayPlacement::RIGHT,
                       0,
                       DisplayPlacement::TOP_LEFT) {}

DisplayPlacement::DisplayPlacement(Position position, int offset)
    : DisplayPlacement(kInvalidDisplayId,
                       kInvalidDisplayId,
                       position,
                       offset,
                       DisplayPlacement::TOP_LEFT) {}

DisplayPlacement::DisplayPlacement(Position position,
                                   int offset,
                                   OffsetReference offset_reference)
    : DisplayPlacement(kInvalidDisplayId,
                       kInvalidDisplayId,
                       position,
                       offset,
                       offset_reference) {}

DisplayPlacement::DisplayPlacement(int64_t display_id,
                                   int64_t parent_display_id,
                                   Position position,
                                   int offset,
                                   OffsetReference offset_reference)
    : display_id(display_id),
      parent_display_id(parent_display_id),
      position(position),
      offset(offset),
      offset_reference(offset_reference) {
  DCHECK_LE(TOP, position);
  DCHECK_GE(LEFT, position);
  // Set the default value to |position| in case position is invalid.  DCHECKs
  // above doesn't stop in Release builds.
  if (TOP > position || LEFT < position)
    this->position = RIGHT;

  DCHECK_GE(kMaxValidOffset, abs(offset));
}

DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement)
    : display_id(placement.display_id),
      parent_display_id(placement.parent_display_id),
      position(placement.position),
      offset(placement.offset),
      offset_reference(placement.offset_reference) {}

bool DisplayPlacement::operator==(const DisplayPlacement& other) const {
  return display_id == other.display_id &&
         parent_display_id == other.parent_display_id &&
         position == other.position &&
         offset == other.offset &&
         offset_reference == other.offset_reference;
}

bool DisplayPlacement::operator!=(const DisplayPlacement& other) const {
  return !operator==(other);
}

DisplayPlacement& DisplayPlacement::Swap() {
  switch (position) {
    case TOP:
      position = BOTTOM;
      break;
    case BOTTOM:
      position = TOP;
      break;
    case RIGHT:
      position = LEFT;
      break;
    case LEFT:
      position = RIGHT;
      break;
  }
  offset = -offset;
  std::swap(display_id, parent_display_id);
  return *this;
}

std::string DisplayPlacement::ToString() const {
  std::stringstream s;
  if (display_id != kInvalidDisplayId)
    s << "id=" << display_id << ", ";
  if (parent_display_id != kInvalidDisplayId)
    s << "parent=" << parent_display_id << ", ";
  s << PositionToString(position) << ", ";
  s << offset;
  return s.str();
}

// static
std::string DisplayPlacement::PositionToString(Position position) {
  switch (position) {
    case TOP:
      return kTop;
    case RIGHT:
      return kRight;
    case BOTTOM:
      return kBottom;
    case LEFT:
      return kLeft;
  }
  return kUnknown;
}

// static
bool DisplayPlacement::StringToPosition(const base::StringPiece& string,
                                        Position* position) {
  if (string == kTop) {
    *position = TOP;
    return true;
  }

  if (string == kRight) {
    *position = RIGHT;
    return true;
  }

  if (string == kBottom) {
    *position = BOTTOM;
    return true;
  }

  if (string == kLeft) {
    *position = LEFT;
    return true;
  }

  LOG(ERROR) << "Invalid position value:" << string;

  return false;
}

////////////////////////////////////////////////////////////////////////////////
// DisplayLayout

DisplayLayout::DisplayLayout()
    : default_unified(true), primary_id(kInvalidDisplayId) {}

DisplayLayout::~DisplayLayout() {}

void DisplayLayout::ApplyToDisplayList(Displays* display_list,
                                       std::vector<int64_t>* updated_ids,
                                       int minimum_offset_overlap) {
  if (placement_list.empty())
    return;

  if (!DisplayLayout::Validate(DisplayListToDisplayIdList(*display_list),
                               *this)) {
    // Prevent invalid and non-relevant display layouts.
    return;
  }

  // Layout from primary, then dependent displays.
  std::set<int64_t> parents;
  std::set<int64_t> updated_displays;
  parents.insert(primary_id);
  while (parents.size()) {
    int64_t parent_id = *parents.begin();
    parents.erase(parent_id);
    for (const DisplayPlacement& placement : placement_list) {
      if (placement.parent_display_id == parent_id) {
        if (ApplyDisplayPlacement(placement, display_list,
                                  minimum_offset_overlap)) {
          updated_displays.insert(placement.display_id);
        }
        parents.insert(placement.display_id);
      }
    }
  }

  // Now that all the placements have been applied, we must detect and fix any
  // overlapping displays.
  DeIntersectDisplays(primary_id, display_list, &placement_list,
                      &updated_displays);

  if (updated_ids) {
    updated_ids->insert(updated_ids->begin(), updated_displays.begin(),
                        updated_displays.end());
  }
}

// static
bool DisplayLayout::Validate(const DisplayIdList& list,
                             const DisplayLayout& layout) {
  // The primary display should be in the list.
  if (!IsIdInList(layout.primary_id, list)) {
    LOG(ERROR) << "The primary id: " << layout.primary_id
               << " is not in the id list.";
    return false;
  }

  // Unified mode, or mirror mode switched from unified mode,
  // may not have the placement yet.
  if (layout.placement_list.size() == 0u)
    return true;

  bool has_primary_as_parent = false;
  // The placement list must be sorted by the first 8 bits of the display IDs.
  int64_t prev_id = std::numeric_limits<int8_t>::min();
  for (const auto& placement : layout.placement_list) {
    // Placements are sorted by display_id.
    if (prev_id >= (placement.display_id & 0xFF)) {
      LOG(ERROR) << "PlacementList must be sorted by first 8 bits of"
                 << " display_id ";
      return false;
    }
    prev_id = (placement.display_id & 0xFF);
    if (placement.display_id == kInvalidDisplayId) {
      LOG(ERROR) << "display_id is not initialized";
      return false;
    }
    if (placement.parent_display_id == kInvalidDisplayId) {
      LOG(ERROR) << "display_parent_id is not initialized";
      return false;
    }
    if (placement.display_id == placement.parent_display_id) {
      LOG(ERROR) << "display_id must not be same as parent_display_id";
      return false;
    }
    if (!IsIdInList(placement.display_id, list)) {
      LOG(ERROR) << "display_id is not in the id list:" << placement.ToString();
      return false;
    }

    if (!IsIdInList(placement.parent_display_id, list)) {
      LOG(ERROR) << "parent_display_id is not in the id list:"
                 << placement.ToString();
      return false;
    }
    has_primary_as_parent |= layout.primary_id == placement.parent_display_id;
  }
  if (!has_primary_as_parent)
    LOG(ERROR) << "At least, one placement must have the primary as a parent.";
  return has_primary_as_parent;
}

std::unique_ptr<DisplayLayout> DisplayLayout::Copy() const {
  std::unique_ptr<DisplayLayout> copy(new DisplayLayout);
  for (const auto& placement : placement_list)
    copy->placement_list.push_back(placement);
  copy->default_unified = default_unified;
  copy->primary_id = primary_id;
  return copy;
}

void DisplayLayout::SwapPrimaryDisplay(int64_t new_primary_id) {
  if (primary_id == new_primary_id)
    return;

  // Build a map of the *original* |display_id| for each placement.
  std::unordered_map<int64_t, DisplayPlacement*> id_to_placement;
  for (auto& placement : placement_list)
    id_to_placement[placement.display_id] = &placement;

  // Swap placements so that |new_primary_id| is the display that placements are
  // anchored on and set |primary_id|.
  int64_t swap_display_id = new_primary_id;
  while (swap_display_id != primary_id) {
    DisplayPlacement* placement = id_to_placement.at(swap_display_id);
    swap_display_id = placement->parent_display_id;
    placement->Swap();
  }
  std::sort(placement_list.begin(), placement_list.end(), ComparePlacements);
  primary_id = new_primary_id;
}

bool DisplayLayout::HasSamePlacementList(const DisplayLayout& layout) const {
  return placement_list == layout.placement_list;
}

std::string DisplayLayout::ToString() const {
  std::stringstream s;
  s << "primary=" << primary_id;
  if (default_unified)
    s << ", default_unified";
  bool added = false;
  for (const auto& placement : placement_list) {
    s << (added ? "),(" : " [(");
    s << placement.ToString();
    added = true;
  }
  if (added)
    s << ")]";
  return s.str();
}

DisplayPlacement DisplayLayout::FindPlacementById(int64_t display_id) const {
  const auto iter =
      std::find_if(placement_list.begin(), placement_list.end(),
                   [display_id](const DisplayPlacement& placement) {
                     return placement.display_id == display_id;
                   });
  return (iter == placement_list.end()) ? DisplayPlacement()
                                        : DisplayPlacement(*iter);
}

// Creates a display::DisplayPlacement value for |rectangle| relative to the
// |reference| rectangle.
// The layout consists of two values:
//   - position: Whether the rectangle is positioned left, right, over or under
//     the reference.
//   - offset: The rectangle's offset from the reference origin along the axis
//     opposite the position direction (if the rectangle is left or right along
//     y-axis, otherwise along x-axis).
// The rectangle's position is calculated by dividing the space in areas defined
// by the |reference|'s diagonals and finding the area |rectangle|'s center
// point belongs. If the |rectangle| in the calculated layout does not share a
// part of the bounds with the |reference|, the |rectangle| position in set to
// the more suitable neighboring position (e.g. if |rectangle| is completely
// over the |reference| top bound, it will be set to TOP) and the layout is
// recalculated with the new position. This is to handle the case where the
// rectangle shares an edge with the reference, but it's center is not in the
// same area as the reference's edge, e.g.
//
// +---------------------+
// |                     |
// | REFERENCE           |
// |                     |
// |                     |
// +---------------------+
//                 +-------------------------------------------------+
//                 | RECTANGLE               x                       |
//                 +-------------------------------------------------+
//
// The rectangle shares an egde with the reference's bottom edge, but it's
// center point is in the left area.

// static
DisplayPlacement DisplayLayout::CreatePlacementForRectangles(
    const gfx::Rect& reference,
    const gfx::Rect& rectangle) {
  // Translate coordinate system so origin is in the reference's top left point
  // (so the reference's down-diagonal vector starts in the (0, 0)) and scale it
  // up by two (to avoid division when calculating the rectangle's center
  // point).
  gfx::Point center(2 * (rectangle.x() - reference.x()) + rectangle.width(),
                    2 * (rectangle.y() - reference.y()) + rectangle.height());
  gfx::Point down_diag(2 * reference.width(), 2 * reference.height());

  bool is_top_right = IsPointOverRadiusVector(center, down_diag);

  // Translate the coordinate system again, so the bottom right point of the
  // reference is origin (so the reference's up-diagonal starts at (0, 0)).
  // Note that the coordinate system is scaled by 2.
  center.Offset(0, -2 * reference.height());
  // Choose the vector orientation so the points on the diagonal are considered
  // to be left.
  gfx::Point up_diag(-2 * reference.width(), 2 * reference.height());

  bool is_bottom_right = IsPointOverRadiusVector(center, up_diag);

  DisplayPlacement::Position position;
  if (is_top_right) {
    position =
        is_bottom_right ? DisplayPlacement::RIGHT : DisplayPlacement::TOP;
  } else {
    position =
        is_bottom_right ? DisplayPlacement::BOTTOM : DisplayPlacement::LEFT;
  }

  // If the rectangle with the calculated position would not have common side
  // with the reference, try to position it so it shares another edge with the
  // reference.
  if (is_top_right == is_bottom_right) {
    if (rectangle.y() > reference.bottom()) {
      // The rectangle is left or right, but completely under the reference.
      position = DisplayPlacement::BOTTOM;
    } else if (rectangle.bottom() < reference.y()) {
      // The rectangle is left or right, but completely over the reference.
      position = DisplayPlacement::TOP;
    }
  } else {
    if (rectangle.x() > reference.right()) {
      // The rectangle is over or under, but completely right of the reference.
      position = DisplayPlacement::RIGHT;
    } else if (rectangle.right() < reference.x()) {
      // The rectangle is over or under, but completely left of the reference.
      position = DisplayPlacement::LEFT;
    }
  }
  int offset = (position == DisplayPlacement::LEFT ||
                position == DisplayPlacement::RIGHT)
                   ? rectangle.y()
                   : rectangle.x();
  return DisplayPlacement(position, offset);
}

// static
bool DisplayLayout::ApplyDisplayPlacement(const DisplayPlacement& placement,
                                          Displays* display_list,
                                          int minimum_offset_overlap) {
  const Display& parent_display =
      *FindDisplayById(display_list, placement.parent_display_id);
  DCHECK(parent_display.is_valid());
  Display* target_display = FindDisplayById(display_list, placement.display_id);
  gfx::Rect old_bounds(target_display->bounds());
  DCHECK(target_display);

  const gfx::Rect& parent_bounds = parent_display.bounds();
  const gfx::Rect& target_bounds = target_display->bounds();
  gfx::Point new_target_origin = parent_bounds.origin();

  DisplayPlacement::Position position = placement.position;

  // Ignore the offset in case the target display doesn't share edges with
  // the parent display.
  int offset = placement.offset;
  if (position == DisplayPlacement::TOP ||
      position == DisplayPlacement::BOTTOM) {
    if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT)
      offset = parent_bounds.width() - offset - target_bounds.width();

    offset = std::min(offset, parent_bounds.width() - minimum_offset_overlap);
    offset = std::max(offset, -target_bounds.width() + minimum_offset_overlap);
  } else {
    if (placement.offset_reference == DisplayPlacement::BOTTOM_RIGHT)
      offset = parent_bounds.height() - offset - target_bounds.height();

    offset = std::min(offset, parent_bounds.height() - minimum_offset_overlap);
    offset = std::max(offset, -target_bounds.height() + minimum_offset_overlap);
  }
  switch (position) {
    case DisplayPlacement::TOP:
      new_target_origin.Offset(offset, -target_bounds.height());
      break;
    case DisplayPlacement::RIGHT:
      new_target_origin.Offset(parent_bounds.width(), offset);
      break;
    case DisplayPlacement::BOTTOM:
      new_target_origin.Offset(offset, parent_bounds.height());
      break;
    case DisplayPlacement::LEFT:
      new_target_origin.Offset(-target_bounds.width(), offset);
      break;
  }

  gfx::Insets insets = target_display->GetWorkAreaInsets();
  target_display->set_bounds(
      gfx::Rect(new_target_origin, target_bounds.size()));
  target_display->UpdateWorkAreaFromInsets(insets);

  return old_bounds != target_display->bounds();
}

}  // namespace display
