// Copyright 2014 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 "athena/wm/split_view_controller.h"

#include <cmath>

#include "athena/screen/public/screen_manager.h"
#include "athena/wm/public/window_manager.h"
#include "athena/wm/window_list_provider_impl.h"
#include "base/bind.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/compositor/closure_animation_observer.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/views/background.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/root_view_targeter.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"

namespace athena {

namespace {

const int kDragHandleWidth = 4;
const int kDragHandleHeight = 80;
const int kDragHandleMargin = 1;
const int kDividerWidth = kDragHandleWidth + 2 * kDragHandleMargin;

// Max distance from the scroll end position to the middle of the screen where
// we would go into the split view mode.
const float kMaxDistanceFromMiddle = 120.0f;

// The minimum x-velocity required for a fling to disengage split view mode
// when targeted to the drag handle.
const float kMinFlingVelocity = 800.0f;

enum WindowToActivate {
  // Do not activate either of |left_window_| or |right_window_|.
  WINDOW_NONE,
  // Activate |left_window_|.
  WINDOW_LEFT,
  // Activate |right_window_|.
  WINDOW_RIGHT
};

// Always returns the same target.
class StaticViewTargeterDelegate : public views::ViewTargeterDelegate {
 public:
  explicit StaticViewTargeterDelegate(views::View* target) : target_(target) {}

  ~StaticViewTargeterDelegate() override {}

 private:
  // views::ViewTargeterDelegate:
  virtual views::View* TargetForRect(views::View* root,
                                     const gfx::Rect& rect) override {
    return target_;
  }

  // Not owned.
  views::View* target_;

  DISALLOW_COPY_AND_ASSIGN(StaticViewTargeterDelegate);
};

// Expands the effective target area of the window of the widget containing the
// specified view. If the view is large enough to begin with, there should be
// no change from the default targeting behavior.
class PriorityWindowTargeter : public aura::WindowTargeter,
                               public aura::WindowObserver {
 public:
  explicit PriorityWindowTargeter(views::View* priority_view)
      : priority_view_(priority_view) {
    CHECK(priority_view->GetWidget());
    window_ = priority_view->GetWidget()->GetNativeWindow();
    CHECK(window_);
    window_->AddObserver(this);
  }

  ~PriorityWindowTargeter() override { window_->RemoveObserver(this); }

 private:
  // aura::WindowTargeter:
  ui::EventTarget* FindTargetForLocatedEvent(ui::EventTarget* root,
                                             ui::LocatedEvent* event) override {
    if (!window_ || (event->type() != ui::ET_TOUCH_PRESSED))
      return WindowTargeter::FindTargetForLocatedEvent(root, event);
    CHECK_EQ(window_, priority_view_->GetWidget()->GetNativeWindow());

    // Bounds of the view in root window's coordinates.
    gfx::Rect view_bounds = priority_view_->GetBoundsInScreen();
    // If there is a transform on the window's layer - apply it.
    gfx::Transform window_transform = window_->layer()->transform();
    gfx::RectF transformed_bounds_f = view_bounds;
    window_transform.TransformRect(&transformed_bounds_f);
    gfx::Rect transformed_bounds = gfx::Rect(transformed_bounds_f.x(),
                                             transformed_bounds_f.y(),
                                             transformed_bounds_f.width(),
                                             transformed_bounds_f.height());
    // Now expand the bounds to be at least
    // kMinTouchDimension x kMinTouchDimension and target the event to the
    // window if it falls within the expanded bounds
    gfx::Point center = transformed_bounds.CenterPoint();
    gfx::Rect extension_rect = gfx::Rect(
        center.x() - kMinTouchDimension / 2,
        center.y() - kMinTouchDimension / 2,
        kMinTouchDimension,
        kMinTouchDimension);
    gfx::Rect extended_bounds =
        gfx::UnionRects(transformed_bounds, extension_rect);
    if (extended_bounds.Contains(event->root_location())) {
      root->ConvertEventToTarget(window_, event);
      return window_;
    }

    return WindowTargeter::FindTargetForLocatedEvent(root, event);
  }

  // aura::WindowObserver:
  void OnWindowDestroying(aura::Window* window) override {
    DCHECK_EQ(window, window_);
    window_->RemoveObserver(this);
    window_ = nullptr;
  }

  // Minimum dimension of a target to be comfortably touchable.
  // The effective touch target area of |priority_window_| gets expanded so
  // that it's width and height is ayt least |kMinTouchDimension|.
  int const kMinTouchDimension = 26;

  aura::Window* window_;
  views::View* priority_view_;

  DISALLOW_COPY_AND_ASSIGN(PriorityWindowTargeter);
};

// Returns a target transform required to transform |from| to |to|.
gfx::Transform GetTransformForBounds(const gfx::Rect& from,
                                     const gfx::Rect& to) {
  gfx::Transform transform;
  transform.Translate(to.x() - from.x(), to.y() - from.y());
  transform.Scale(to.width() / static_cast<float>(from.width()),
                  to.height() / static_cast<float>(from.height()));
  return transform;
}

bool IsLandscapeOrientation(gfx::Display::Rotation rotation) {
  return rotation == gfx::Display::ROTATE_0 ||
         rotation == gfx::Display::ROTATE_180;
}

}  // namespace

SplitViewController::SplitViewController(
    aura::Window* container,
    WindowListProviderImpl* window_list_provider)
    : state_(INACTIVE),
      container_(container),
      window_list_provider_(window_list_provider),
      left_window_(nullptr),
      right_window_(nullptr),
      divider_position_(0),
      divider_scroll_start_position_(0),
      divider_widget_(nullptr),
      drag_handle_(nullptr),
      weak_factory_(this) {
  window_list_provider_->AddObserver(this);
}

SplitViewController::~SplitViewController() {
  window_list_provider_->RemoveObserver(this);
}

bool SplitViewController::CanActivateSplitViewMode() const {
  // TODO(mfomitchev): return false in full screen.
  return (!IsSplitViewModeActive() &&
              window_list_provider_->GetWindowList().size() >= 2 &&
              IsLandscapeOrientation(gfx::Screen::GetNativeScreen()->
                  GetDisplayNearestWindow(container_).rotation()));
}

bool SplitViewController::IsSplitViewModeActive() const {
  return state_ == ACTIVE;
}

void SplitViewController::ActivateSplitMode(aura::Window* left,
                                            aura::Window* right,
                                            aura::Window* to_activate) {
  const aura::Window::Windows& windows = window_list_provider_->GetWindowList();
  aura::Window::Windows::const_reverse_iterator iter = windows.rbegin();
  if (state_ == ACTIVE) {
    if (!left && left_window_ != right)
      left = left_window_;
    if (!right && right_window_ != left)
      right = right_window_;
  }

  if (!left && iter != windows.rend()) {
    left = *iter;
    iter++;
    if (left == right && iter != windows.rend()) {
      left = *iter;
      iter++;
    }
  }

  if (!right && iter != windows.rend()) {
    right = *iter;
    iter++;
    if (right == left && iter != windows.rend()) {
      right = *iter;
      iter++;
    }
  }

  to_hide_.clear();
  if (left_window_ && left_window_ != left && left_window_ != right)
    to_hide_.push_back(left_window_);
  if (right_window_ && right_window_ != left && right_window_ != right)
    to_hide_.push_back(right_window_);

  left_window_ = left;
  right_window_ = right;

  divider_position_ = GetDefaultDividerPosition();
  SetState(ACTIVE);
  UpdateLayout(true);

  aura::client::ActivationClient* activation_client =
      aura::client::GetActivationClient(container_->GetRootWindow());
  aura::Window* active_window = activation_client->GetActiveWindow();
  if (to_activate) {
    CHECK(to_activate == left_window_ || to_activate == right_window_);
    wm::ActivateWindow(to_activate);
  } else if (active_window != left_window_ &&
             active_window != right_window_) {
    // A window which does not belong to an activity could be active.
    wm::ActivateWindow(left_window_);
  }
  active_window = activation_client->GetActiveWindow();

  if (active_window == left_window_)
    window_list_provider_->StackWindowBehindTo(right_window_, left_window_);
  else
    window_list_provider_->StackWindowBehindTo(left_window_, right_window_);
}

void SplitViewController::ReplaceWindow(aura::Window* window,
                                        aura::Window* replace_with) {
  CHECK(IsSplitViewModeActive());
  CHECK(replace_with);
  CHECK(window == left_window_ || window == right_window_);
  CHECK(replace_with != left_window_ && replace_with != right_window_);
  DCHECK(window_list_provider_->IsValidWindow(replace_with));

  aura::Window* not_replaced = nullptr;
  if (window == left_window_) {
    left_window_ = replace_with;
    not_replaced = right_window_;
  } else {
    right_window_ = replace_with;
    not_replaced = left_window_;
  }
  UpdateLayout(false);

  wm::ActivateWindow(replace_with);
  window_list_provider_->StackWindowBehindTo(not_replaced, replace_with);

  window->SetTransform(gfx::Transform());
  window->Hide();
}

void SplitViewController::DeactivateSplitMode() {
  CHECK_EQ(ACTIVE, state_);
  SetState(INACTIVE);
  UpdateLayout(false);
  left_window_ = right_window_ = nullptr;
}

void SplitViewController::InitializeDivider() {
  CHECK(!divider_widget_);
  CHECK(!drag_handle_);

  drag_handle_ = CreateDragHandleView(DRAG_HANDLE_HORIZONTAL,
                                      this,
                                      kDragHandleWidth,
                                      kDragHandleHeight);
  views::View* content_view = new views::View;
  content_view->set_background(
      views::Background::CreateSolidBackground(SK_ColorBLACK));
  views::BoxLayout* layout =
      new views::BoxLayout(views::BoxLayout::kHorizontal,
                           kDragHandleMargin,
                           kDragHandleMargin,
                           0);
  layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
  layout->set_cross_axis_alignment(
      views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
  content_view->SetLayoutManager(layout);
  content_view->AddChildView(drag_handle_);

  divider_widget_ = new views::Widget();
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
  params.parent = container_;
  params.bounds = gfx::Rect(-kDividerWidth / 2,
                            0,
                            kDividerWidth,
                            container_->bounds().height());
  divider_widget_->Init(params);
  divider_widget_->SetContentsView(content_view);

  // Install a static view targeter on the root view which always targets
  // divider_view.
  // TODO(mfomitchev,tdanderson): This should not be needed:
  // 1. crbug.com/414339 - divider_view is the only view and it completely
  //    overlaps the root view.
  // 2. The logic in ViewTargeterDelegate::TargetForRect could be improved to
  //    work better for views that are narrow in one dimension and long in
  //    another dimension.
  views::internal::RootView* root_view =
      static_cast<views::internal::RootView*>(divider_widget_->GetRootView());
  view_targeter_delegate_.reset(new StaticViewTargeterDelegate(drag_handle_));
  views::ViewTargeter* targeter =
      new views::RootViewTargeter(view_targeter_delegate_.get(), root_view);
  divider_widget_->GetRootView()->SetEventTargeter(
      scoped_ptr<views::ViewTargeter>(targeter));
}

void SplitViewController::HideDivider() {
  divider_widget_->Hide();
  window_targeter_.reset();
}

void SplitViewController::ShowDivider() {
  divider_widget_->Show();
  if (!window_targeter_) {
    scoped_ptr<ui::EventTargeter> window_targeter =
        scoped_ptr<ui::EventTargeter>(new PriorityWindowTargeter(drag_handle_));
    window_targeter_.reset(
        new aura::ScopedWindowTargeter(container_, window_targeter.Pass()));
  }
}

gfx::Rect SplitViewController::GetLeftAreaBounds() {
  gfx::Rect work_area =
      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area();
  return gfx::Rect(
      0, 0, divider_position_ - kDividerWidth / 2, work_area.height());
}

gfx::Rect SplitViewController::GetRightAreaBounds() {
  gfx::Rect work_area =
      gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area();
  int container_width = container_->bounds().width();
  return gfx::Rect(divider_position_ + kDividerWidth / 2,
                   0,
                   container_width - divider_position_ - kDividerWidth / 2,
                   work_area.height());
}

void SplitViewController::OnWindowAddedToList(aura::Window* added_window) {
}

void SplitViewController::OnWindowRemovedFromList(aura::Window* removed_window,
                                                  int index) {
  if (!IsSplitViewModeActive() ||
      (removed_window != left_window_ && removed_window != right_window_)) {
    return;
  }

  DCHECK(!window_list_provider_->IsWindowInList(removed_window));

  const aura::Window::Windows windows = window_list_provider_->GetWindowList();
  CHECK_GE(static_cast<int>(windows.size()), 1);
  DCHECK_GE(index, static_cast<int>(windows.size() - 1));
  DCHECK_LE(index, static_cast<int>(windows.size()));

  if (windows.size() == 1) {
    DeactivateSplitMode();
    return;
  }

  aura::Window* next_window = *(windows.rbegin() + 1);
  if (removed_window == left_window_) {
    CHECK(right_window_ == windows.back());
    left_window_ = next_window;
  } else {
    CHECK(left_window_ == windows.back());
    CHECK(removed_window == right_window_);
    right_window_ = next_window;
  }
  UpdateLayout(false);
}

void SplitViewController::SetState(SplitViewController::State state) {
  if (state_ == state)
    return;

  if (divider_widget_ == nullptr)
    InitializeDivider();

  state_ = state;

  ScreenManager::Get()->SetRotationLocked(state_ != INACTIVE);
  if (state == INACTIVE)
    HideDivider();
  else
    ShowDivider();
}

void SplitViewController::UpdateLayout(bool animate) {
  CHECK(left_window_);
  CHECK(right_window_);
  // Splitview can be activated from SplitViewController::ActivateSplitMode or
  // SplitViewController::ScrollEnd. Additionally we don't want to rotate the
  // screen while engaging splitview (i.e. state_ == SCROLLING).
  if (state_ == INACTIVE && !animate) {
    gfx::Rect work_area =
        gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area();
    aura::Window* top_window = window_list_provider_->GetWindowList().back();
    if (top_window != left_window_) {
      // TODO(mfomitchev): Use to_hide_ instead
      left_window_->Hide();
      right_window_->SetBounds(gfx::Rect(work_area.size()));
    }
    if (top_window != right_window_) {
      left_window_->SetBounds(gfx::Rect(work_area.size()));
      // TODO(mfomitchev): Use to_hide_ instead
      right_window_->Hide();
    }
    SetWindowTransforms(
        gfx::Transform(), gfx::Transform(), gfx::Transform(), false);
    return;
  }

  left_window_->Show();
  right_window_->Show();

  gfx::Transform divider_transform;
  divider_transform.Translate(divider_position_, 0);
  if (state_ == ACTIVE) {
    if (animate) {
      gfx::Transform left_transform =
          GetTransformForBounds(left_window_->bounds(), GetLeftAreaBounds());
      gfx::Transform right_transform =
          GetTransformForBounds(right_window_->bounds(), GetRightAreaBounds());
      SetWindowTransforms(
          left_transform, right_transform, divider_transform, true);
    } else {
      left_window_->SetBounds(GetLeftAreaBounds());
      right_window_->SetBounds(GetRightAreaBounds());
      SetWindowTransforms(
          gfx::Transform(), gfx::Transform(), divider_transform, false);
    }
  } else {
    gfx::Transform left_transform;
    gfx::Transform right_transform;
    gfx::Rect left_area_bounds = GetLeftAreaBounds();
    gfx::Rect right_area_bounds = GetRightAreaBounds();
    // If the width of the window is greater than the width of the area which it
    // is supposed to occupy - translate the window. Otherwise scale the window
    // up to fill the target area.
    if (left_window_->bounds().width() >= left_area_bounds.width()) {
      left_transform.Translate(
          left_area_bounds.right() - left_window_->bounds().right(), 0);
    } else {
      left_transform =
          GetTransformForBounds(left_window_->bounds(), left_area_bounds);
    }
    if (right_window_->bounds().width() >= right_area_bounds.width()) {
      right_transform.Translate(
          right_area_bounds.x() - right_window_->bounds().x(), 0);
    } else {
      right_transform =
          GetTransformForBounds(right_window_->bounds(), right_area_bounds);
    }
    SetWindowTransforms(
        left_transform, right_transform, divider_transform, animate);
  }
  // Note: |left_window_| and |right_window_| may be nullptr if calling
  // SetWindowTransforms():
  // - caused the in-progress animation to abort.
  // - started a zero duration animation.
}

void SplitViewController::SetWindowTransforms(
    const gfx::Transform& left_transform,
    const gfx::Transform& right_transform,
    const gfx::Transform& divider_transform,
    bool animate) {
  if (animate) {
    ui::ScopedLayerAnimationSettings left_settings(
        left_window_->layer()->GetAnimator());
    left_settings.SetPreemptionStrategy(
        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
    left_window_->SetTransform(left_transform);

    ui::ScopedLayerAnimationSettings divider_widget_settings(
        divider_widget_->GetNativeWindow()->layer()->GetAnimator());
    divider_widget_settings.SetPreemptionStrategy(
        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
    divider_widget_->GetNativeWindow()->SetTransform(divider_transform);

    ui::ScopedLayerAnimationSettings right_settings(
        right_window_->layer()->GetAnimator());
    right_settings.SetPreemptionStrategy(
        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
    right_settings.AddObserver(new ui::ClosureAnimationObserver(
        base::Bind(&SplitViewController::OnAnimationCompleted,
                   weak_factory_.GetWeakPtr())));
    right_window_->SetTransform(right_transform);
  } else {
    left_window_->SetTransform(left_transform);
    divider_widget_->GetNativeWindow()->SetTransform(divider_transform);
    right_window_->SetTransform(right_transform);
  }
}

void SplitViewController::OnAnimationCompleted() {
  // Animation can be cancelled when deactivated.
  if (left_window_ == nullptr)
    return;
  UpdateLayout(false);

  for (size_t i = 0; i < to_hide_.size(); ++i)
    to_hide_[i]->Hide();
  to_hide_.clear();

  if (state_ == INACTIVE) {
    left_window_ = nullptr;
    right_window_ = nullptr;
  }
}

int SplitViewController::GetDefaultDividerPosition() {
  return container_->GetBoundsInScreen().width() / 2;
}

float SplitViewController::GetMaxDistanceFromMiddleForTest() const {
  return kMaxDistanceFromMiddle;
}

float SplitViewController::GetMinFlingVelocityForTest() const {
  return kMinFlingVelocity;
}

///////////////////////////////////////////////////////////////////////////////
// DragHandleScrollDelegate:

void SplitViewController::HandleScrollBegin(float delta) {
  CHECK(state_ == ACTIVE);
  state_ = SCROLLING;
  divider_scroll_start_position_ = GetDefaultDividerPosition();
  divider_position_ = divider_scroll_start_position_ + delta;
  UpdateLayout(false);
}

void SplitViewController::HandleScrollEnd(float velocity) {
  if (state_ != SCROLLING)
    return;

  int delta = GetDefaultDividerPosition() - divider_position_;
  WindowToActivate window = WINDOW_NONE;
  if (std::abs(velocity) > kMinFlingVelocity)
    window = velocity > 0 ? WINDOW_LEFT : WINDOW_RIGHT;
  else if (std::abs(delta) > kMaxDistanceFromMiddle)
    window = delta > 0 ? WINDOW_RIGHT : WINDOW_LEFT;

  switch (window) {
    case WINDOW_NONE:
      divider_position_ = GetDefaultDividerPosition();
      SetState(ACTIVE);
      break;
    case WINDOW_LEFT:
      divider_position_ = container_->GetBoundsInScreen().width();
      SetState(INACTIVE);
      wm::ActivateWindow(left_window_);
      break;
    case WINDOW_RIGHT:
      divider_position_ = 0;
      SetState(INACTIVE);
      wm::ActivateWindow(right_window_);
      break;
  }

  UpdateLayout(true);
}

void SplitViewController::HandleScrollUpdate(float delta) {
  if (state_ != SCROLLING)
    return;
  divider_position_ = divider_scroll_start_position_ + delta;
  UpdateLayout(false);
}

///////////////////////////////////////////////////////////////////////////////
// WindowManagerObserver:

void SplitViewController::OnOverviewModeEnter() {
  if (divider_widget_)
    HideDivider();
}

void SplitViewController::OnOverviewModeExit() {
  if (state_ != INACTIVE)
    ShowDivider();
}

void SplitViewController::OnSplitViewModeEnter() {
}

void SplitViewController::OnSplitViewModeExit() {
}

}  // namespace athena
