// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/ui_navigation/scroll_engine/scroll_engine.h"

#include <algorithm>

#include "base/logging.h"
#include "cobalt/dom/pointer_event.h"
#include "cobalt/math/clamp.h"

namespace cobalt {
namespace ui_navigation {
namespace scroll_engine {

namespace {

const base::TimeDelta kMaxFreeScrollDuration =
    base::TimeDelta::FromMilliseconds(700);

void BoundValuesByNavItemBounds(scoped_refptr<ui_navigation::NavItem> nav_item,
                                float* x, float* y) {
  float scroll_top_lower_bound;
  float scroll_left_lower_bound;
  float scroll_top_upper_bound;
  float scroll_left_upper_bound;
  nav_item->GetBounds(&scroll_top_lower_bound, &scroll_left_lower_bound,
                      &scroll_top_upper_bound, &scroll_left_upper_bound);

  *x = std::min(scroll_left_upper_bound, *x);
  *x = std::max(scroll_left_lower_bound, *x);
  *y = std::min(scroll_top_upper_bound, *y);
  *y = std::max(scroll_top_lower_bound, *y);
}

math::Vector2dF BoundValuesByNavItemBounds(
    scoped_refptr<ui_navigation::NavItem> nav_item, math::Vector2dF vector) {
  float x = vector.x();
  float y = vector.y();
  BoundValuesByNavItemBounds(nav_item, &x, &y);
  vector.set_x(x);
  vector.set_y(y);
  return vector;
}

bool ShouldFreeScroll(scoped_refptr<ui_navigation::NavItem> scroll_container,
                      math::Vector2dF drag_vector) {
  float x = drag_vector.x();
  float y = drag_vector.y();
  bool scrolling_right = x > 0;
  bool scrolling_down = y > 0;
  bool scrolling_left = !scrolling_right;
  bool scrolling_up = !scrolling_down;

  float scroll_top_lower_bound, scroll_left_lower_bound, scroll_top_upper_bound,
      scroll_left_upper_bound;
  float offset_x, offset_y;
  scroll_container->GetBounds(&scroll_top_lower_bound, &scroll_left_lower_bound,
                              &scroll_top_upper_bound,
                              &scroll_left_upper_bound);
  scroll_container->GetContentOffset(&offset_x, &offset_y);

  bool can_scroll_left = scroll_left_lower_bound < offset_x;
  bool can_scroll_right = scroll_left_upper_bound > offset_x;
  bool can_scroll_up = scroll_top_lower_bound < offset_y;
  bool can_scroll_down = scroll_top_upper_bound > offset_y;
  return (
      ((can_scroll_left && scrolling_left) ||
       (can_scroll_right && scrolling_right)) &&
      ((can_scroll_down && scrolling_down) || (can_scroll_up && scrolling_up)));
}

void ScrollNavItemWithVector(scoped_refptr<NavItem> nav_item,
                             math::Vector2dF vector) {
  float offset_x;
  float offset_y;
  nav_item->GetContentOffset(&offset_x, &offset_y);
  offset_x += vector.x();
  offset_y += vector.y();
  BoundValuesByNavItemBounds(nav_item, &offset_x, &offset_y);

  nav_item->SetContentOffset(offset_x, offset_y);
}

float GetMaxAbsoluteDimension(math::Vector2dF vector) {
  return std::abs(vector.x()) >= std::abs(vector.y()) ? vector.x() : vector.y();
}

math::Vector2dF GetVelocityInMilliseconds(
    EventPositionWithTimeStamp previous_event,
    EventPositionWithTimeStamp current_event) {
  auto time_delta = current_event.time_stamp - previous_event.time_stamp;
  auto distance_delta = current_event.position - previous_event.position;

  // Don't recognize infinite velocity.
  if (time_delta.is_zero()) {
    return math::Vector2dF(0, 0);
  }

  distance_delta.Scale(static_cast<float>(1.f / time_delta.InMilliseconds()));
  return distance_delta;
}

math::Vector2dF GetNewTarget(EventPositionWithTimeStamp previous_event,
                             EventPositionWithTimeStamp current_event) {
  auto velocity = GetVelocityInMilliseconds(previous_event, current_event);
  velocity.Scale(kMaxFreeScrollDuration.InMilliseconds());
  velocity.Scale(-1);
  return current_event.position + velocity;
}

math::Vector2dF GetNewDelta(EventPositionWithTimeStamp previous_event,
                            EventPositionWithTimeStamp current_event) {
  auto new_target = GetNewTarget(previous_event, current_event);
  return new_target - current_event.position;
}

base::TimeDelta GetAnimationDurationTimeBound(
    EventPositionWithTimeStamp previous_event,
    EventPositionWithTimeStamp current_event) {
  const float time_bound_multiplier = 2.5f;
  auto time_delta = current_event.time_stamp - previous_event.time_stamp;
  return time_delta * time_bound_multiplier;
}

base::TimeDelta GetAnimationDurationEaseInOutBound(
    EventPositionWithTimeStamp previous_event,
    EventPositionWithTimeStamp current_event) {
  auto new_delta = GetNewDelta(previous_event, current_event);
  auto duration = std::sqrt(std::abs(GetMaxAbsoluteDimension(new_delta)));
  return base::TimeDelta::FromMillisecondsD(duration);
}

base::TimeDelta GetAnimationDuration(EventPositionWithTimeStamp previous_event,
                                     EventPositionWithTimeStamp current_event) {
  // TODO(b/265864360): Duration should be calculated as it is in the comment
  //                    below, but it seems to always be too small. Re-evaluate
  //                    once something workable is in.
  // auto duration_time_bound =
  //     GetAnimationDurationTimeBound(previous_event, current_event);
  // auto ease_in_out_bound =
  //     GetAnimationDurationEaseInOutBound(previous_event, current_event);
  // auto min_bound = duration_time_bound < ease_in_out_bound ?
  // duration_time_bound
  //                                                          :
  //                                                          ease_in_out_bound;
  // return min_bound < kMaxFreeScrollDuration ? min_bound
  //                                           : kMaxFreeScrollDuration;
  return kMaxFreeScrollDuration;
}

float GetAnimationSlope(EventPositionWithTimeStamp previous_event,
                        EventPositionWithTimeStamp current_event) {
  auto animation_duration = GetAnimationDuration(previous_event, current_event);
  auto time_delta = previous_event.time_stamp - current_event.time_stamp;
  if (time_delta.is_zero()) {
    return 0.f;
  }
  auto slope = std::abs(animation_duration / time_delta);
  float cubic_bezier_ease_in_out_x1 = 0.42f;
  return math::Clamp(static_cast<float>(slope) * cubic_bezier_ease_in_out_x1,
                     0.f, 1.f);
}

math::Matrix3F CalculateActiveTransform(math::Matrix3F initial_transform) {
  auto active_transform = initial_transform.Inverse();
  if (active_transform.IsZeros()) {
    return math::Matrix3F::Identity();
  }
  return active_transform;
}

}  // namespace

ScrollEngine::ScrollEngine() : active_transform_(math::Matrix3F::Identity()) {}
ScrollEngine::~ScrollEngine() { free_scroll_timer_.Stop(); }

void ScrollEngine::MaybeFreeScrollActiveNavItem() {
  DCHECK(base::MessageLoop::current() == scroll_engine_.message_loop());

  DCHECK(previous_events_.size() == 2);
  if (previous_events_.size() != 2) {
    return;
  }

  auto current_event = previous_events_.back();
  auto previous_event = previous_events_.front();

  auto new_delta = GetNewDelta(previous_event, current_event);
  base::TimeDelta animation_duration =
      GetAnimationDuration(previous_event, current_event);
  float animation_slope = GetAnimationSlope(previous_event, current_event);

  float initial_offset_x;
  float initial_offset_y;
  active_item_->GetContentOffset(&initial_offset_x, &initial_offset_y);
  math::Vector2dF initial_offset(initial_offset_x, initial_offset_y);

  math::Vector2dF target_offset = initial_offset + new_delta;
  target_offset = BoundValuesByNavItemBounds(active_item_, target_offset);

  nav_items_with_decaying_scroll_.push_back(
      FreeScrollingNavItem(active_item_, initial_offset, target_offset,
                           animation_duration, animation_slope));
  if (!free_scroll_timer_.IsRunning()) {
    free_scroll_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(5),
                             this,
                             &ScrollEngine::ScrollNavItemsWithDecayingScroll);
  }

  while (!previous_events_.empty()) {
    previous_events_.pop();
  }
}

void ScrollEngine::HandlePointerEventForActiveItem(
    scoped_refptr<dom::PointerEvent> pointer_event) {
  DCHECK(base::MessageLoop::current() == scroll_engine_.message_loop());

  if (pointer_event->type() == base::Tokens::pointerup()) {
    MaybeFreeScrollActiveNavItem();
    active_item_ = nullptr;
    active_velocity_ = math::Vector2dF(0.0f, 0.0f);
    return;
  }

  if (pointer_event->type() != base::Tokens::pointermove()) {
    return;
  }

  auto transformed_point =
      active_transform_ * math::PointF(pointer_event->x(), pointer_event->y());
  auto current_coordinates =
      math::Vector2dF(transformed_point.x(), transformed_point.y());
  auto current_time = base::Time::FromJsTime(pointer_event->time_stamp());
  if (previous_events_.size() != 2) {
    // This is an error.
    previous_events_.push(
        EventPositionWithTimeStamp(current_coordinates, current_time));
    return;
  }

  previous_events_.pop();
  previous_events_.push(
      EventPositionWithTimeStamp(current_coordinates, current_time));

  auto drag_vector = previous_events_.front().position - current_coordinates;
  if (active_scroll_type_ == ScrollType::Horizontal) {
    drag_vector.set_y(0.0f);
  } else if (active_scroll_type_ == ScrollType::Vertical) {
    drag_vector.set_x(0.0f);
  }

  active_velocity_ = drag_vector;

  ScrollNavItemWithVector(active_item_, drag_vector);
}

void ScrollEngine::HandlePointerEvent(base::Token type,
                                      const dom::PointerEventInit& event) {
  DCHECK(base::MessageLoop::current() == scroll_engine_.message_loop());

  scoped_refptr<dom::PointerEvent> pointer_event(
      new dom::PointerEvent(type, nullptr, event));
  uint32_t pointer_id = pointer_event->pointer_id();
  if (pointer_event->type() == base::Tokens::pointerdown()) {
    events_to_handle_[pointer_id] = pointer_event;
    return;
  }
  if (active_item_) {
    HandlePointerEventForActiveItem(pointer_event);
    return;
  }

  auto last_event_to_handle = events_to_handle_.find(pointer_id);
  if (last_event_to_handle == events_to_handle_.end()) {
    // Pointer events have not come in the appropriate order.
    return;
  }

  if (pointer_event->type() == base::Tokens::pointermove()) {
    if (last_event_to_handle->second->type() == base::Tokens::pointermove() ||
        (math::Vector2dF(last_event_to_handle->second->x(),
                         last_event_to_handle->second->y()) -
         math::Vector2dF(pointer_event->x(), pointer_event->y()))
                .Length() > kDragDistanceThreshold) {
      events_to_handle_[pointer_id] = pointer_event;
    }
  } else if (pointer_event->type() == base::Tokens::pointerup()) {
    if (last_event_to_handle->second->type() == base::Tokens::pointermove()) {
      events_to_handle_[pointer_id] = pointer_event;
    } else {
      events_to_handle_.erase(pointer_id);
    }
  }
}

void ScrollEngine::HandleScrollStart(
    scoped_refptr<ui_navigation::NavItem> scroll_container,
    ScrollType scroll_type, int32_t pointer_id,
    math::Vector2dF initial_coordinates, uint64 initial_time_stamp,
    math::Vector2dF current_coordinates, uint64 current_time_stamp,
    const math::Matrix3F& initial_transform) {
  DCHECK(base::MessageLoop::current() == scroll_engine_.message_loop());
  active_transform_ = CalculateActiveTransform(initial_transform);
  auto initial_point =
      active_transform_ *
      math::PointF(initial_coordinates.x(), initial_coordinates.y());
  auto current_point =
      active_transform_ *
      math::PointF(current_coordinates.x(), current_coordinates.y());
  initial_coordinates.SetVector(initial_point.x(), initial_point.y());
  current_coordinates.SetVector(current_point.x(), current_point.y());

  if (active_item_) {
    events_to_handle_.erase(pointer_id);
    return;
  }

  auto drag_vector = initial_coordinates - current_coordinates;
  if (ShouldFreeScroll(scroll_container, drag_vector)) {
    scroll_type = ScrollType::Free;
  }
  active_item_ = scroll_container;
  active_scroll_type_ = scroll_type;

  if (active_scroll_type_ == ScrollType::Horizontal) {
    drag_vector.set_y(0.0f);
  } else if (active_scroll_type_ == ScrollType::Vertical) {
    drag_vector.set_x(0.0f);
  }

  previous_events_.push(EventPositionWithTimeStamp(
      initial_coordinates, base::Time::FromJsTime(initial_time_stamp)));
  previous_events_.push(EventPositionWithTimeStamp(
      current_coordinates, base::Time::FromJsTime(current_time_stamp)));

  active_velocity_ = drag_vector;
  ScrollNavItemWithVector(active_item_, drag_vector);

  auto event_to_handle = events_to_handle_.find(pointer_id);
  if (event_to_handle != events_to_handle_.end()) {
    HandlePointerEventForActiveItem(event_to_handle->second);
    events_to_handle_.erase(pointer_id);
  }
}

void ScrollEngine::CancelActiveScrollsForNavItems(
    std::vector<scoped_refptr<ui_navigation::NavItem>> scrolls_to_cancel) {
  DCHECK(base::MessageLoop::current() == scroll_engine_.message_loop());

  for (auto scroll_to_cancel : scrolls_to_cancel) {
    for (std::vector<FreeScrollingNavItem>::iterator it =
             nav_items_with_decaying_scroll_.begin();
         it != nav_items_with_decaying_scroll_.end();) {
      if (it->nav_item().get() == scroll_to_cancel.get()) {
        it = nav_items_with_decaying_scroll_.erase(it);
      } else {
        it++;
      }
    }
  }
}

void ScrollEngine::ScrollNavItemsWithDecayingScroll() {
  DCHECK(base::MessageLoop::current() == scroll_engine_.message_loop());

  if (nav_items_with_decaying_scroll_.size() == 0) {
    free_scroll_timer_.Stop();
    return;
  }

  for (std::vector<FreeScrollingNavItem>::iterator it =
           nav_items_with_decaying_scroll_.begin();
       it != nav_items_with_decaying_scroll_.end();) {
    auto current_offset = it->GetCurrentOffset();
    it->nav_item()->SetContentOffset(current_offset.x(), current_offset.y());

    if (it->AnimationIsComplete()) {
      it = nav_items_with_decaying_scroll_.erase(it);
    } else {
      it++;
    }
  }
}

}  // namespace scroll_engine
}  // namespace ui_navigation
}  // namespace cobalt
