// Copyright (c) 2017 The Chromium Embedded Framework Authors.
// Portions 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 "libcef/browser/osr/motion_event_osr.h"

#include <algorithm>

#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"

namespace {

ui::MotionEvent::ToolType CefPointerTypeToMotionEventToolType(
    cef_pointer_type_t pointer_type) {
  switch (pointer_type) {
    case CEF_POINTER_TYPE_TOUCH:
      return ui::MotionEvent::ToolType::FINGER;
    case CEF_POINTER_TYPE_MOUSE:
      return ui::MotionEvent::ToolType::MOUSE;
    case CEF_POINTER_TYPE_PEN:
      return ui::MotionEvent::ToolType::STYLUS;
    case CEF_POINTER_TYPE_ERASER:
      return ui::MotionEvent::ToolType::ERASER;
    case CEF_POINTER_TYPE_UNKNOWN:
      return ui::MotionEvent::ToolType::UNKNOWN;
  }
  NOTREACHED();
  return ui::MotionEvent::ToolType::UNKNOWN;
}

}  // namespace

CefMotionEventOSR::CefMotionEventOSR() {
  std::fill(id_map_, id_map_ + blink::WebTouchEvent::kTouchesLengthCap, -1);
}

CefMotionEventOSR::~CefMotionEventOSR() {}

int CefMotionEventOSR::GetSourceDeviceId(size_t pointer_index) const {
  if (IsValidIndex(pointer_index))
    return pointer(pointer_index).source_device_id;
  else
    return -1;
}

// Returns true if the touch was valid.
bool CefMotionEventOSR::OnTouch(const CefTouchEvent& touch) {
  int id = LookupId(touch.id);
  bool pointer_id_is_active = id != -1;

  if (touch.type == CEF_TET_PRESSED && pointer_id_is_active) {
    // Ignore pressed events for already active touches.
    return false;
  } else if (touch.type != CEF_TET_PRESSED && !pointer_id_is_active) {
    // When a window begins capturing touch events, we could have an active
    // touch stream transfered to us, resulting in touch move or touch up
    // events without associated touch down events. Ignore them.
    return false;
  }

  switch (touch.type) {
    case CEF_TET_PRESSED:
      id = AddId(touch.id);
      if (id == -1)
        return false;
      if (!AddTouch(touch, id))
        return false;
      break;

    case CEF_TET_MOVED: {
      // Discard if touch is stationary.
      int index = FindPointerIndexOfId(id);
      if (IsValidIndex(index) &&
          (touch.x == GetX(index) && touch.y == GetY(index))) {
        return false;
      }
    }
      [[fallthrough]];
    // No break.
    case CEF_TET_RELEASED:
    case CEF_TET_CANCELLED:
      // Removing these touch points needs to be postponed until after the
      // MotionEvent has been dispatched. This cleanup occurs in
      // CleanupRemovedTouchPoints.
      UpdateTouch(touch, id);
      break;
  }

  UpdateCachedAction(touch, id);
  set_unique_event_id(ui::GetNextTouchEventId());
  set_flags(touch.modifiers);
  set_event_time(base::TimeTicks::Now());
  return true;
}

// We can't cleanup removed touch points immediately upon receipt of a
// TouchCancel or TouchRelease, as the MotionEvent needs to be able to report
// information about those touch events. Once the MotionEvent has been
// processed, we call CleanupRemovedTouchPoints to do the required
// book-keeping.
void CefMotionEventOSR::CleanupRemovedTouchPoints(const CefTouchEvent& event) {
  if (event.type != CEF_TET_RELEASED && event.type != CEF_TET_CANCELLED) {
    return;
  }

  DCHECK(GetPointerCount());

  int id = LookupId(event.id);
  int index_to_delete = FindPointerIndexOfId(id);
  set_action_index(-1);
  set_action(ui::MotionEvent::Action::NONE);
  if (IsValidIndex(index_to_delete)) {
    pointer(index_to_delete) = pointer(GetPointerCount() - 1);
    PopPointer();
    RemoveId(event.id);
  }
}

// Reset unchanged touch point to StateStationary for touchmove and touchcancel.
void CefMotionEventOSR::MarkUnchangedTouchPointsAsStationary(
    blink::WebTouchEvent* event,
    const CefTouchEvent& cef_event) {
  int id = LookupId(cef_event.id);
  if (event->GetType() == blink::WebInputEvent::kTouchMove ||
      event->GetType() == blink::WebInputEvent::kTouchCancel) {
    for (size_t i = 0; i < event->touches_length; ++i) {
      if (event->touches[i].id != id)
        event->touches[i].state = blink::WebTouchPoint::kStateStationary;
    }
  }
}

int CefMotionEventOSR::LookupId(int id) {
  if (id == -1)
    return -1;

  for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
    if (id_map_[i] == id) {
      return i;
    }
  }
  return -1;
}

int CefMotionEventOSR::AddId(int id) {
  if (id == -1 || LookupId(id) >= 0)
    return -1;

  for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
    if (id_map_[i] == -1) {
      id_map_[i] = id;
      return i;
    }
  }

  return -1;
}

void CefMotionEventOSR::RemoveId(int id) {
  for (int i = 0; i < blink::WebTouchEvent::kTouchesLengthCap; i++) {
    if (id_map_[i] == id) {
      id_map_[i] = -1;
    }
  }
}

bool CefMotionEventOSR::AddTouch(const CefTouchEvent& touch, int id) {
  if (GetPointerCount() == MotionEvent::MAX_TOUCH_POINT_COUNT)
    return false;

  PushPointer(GetPointerPropertiesFromTouchEvent(touch, id));
  return true;
}

void CefMotionEventOSR::UpdateTouch(const CefTouchEvent& touch, int id) {
  int index_to_update = FindPointerIndexOfId(id);
  if (IsValidIndex(index_to_update))
    pointer(index_to_update) = GetPointerPropertiesFromTouchEvent(touch, id);
}

void CefMotionEventOSR::UpdateCachedAction(const CefTouchEvent& touch, int id) {
  DCHECK(GetPointerCount());
  switch (touch.type) {
    case CEF_TET_PRESSED:
      if (GetPointerCount() == 1) {
        set_action(ui::MotionEvent::Action::DOWN);
      } else {
        set_action(ui::MotionEvent::Action::POINTER_DOWN);
        set_action_index(FindPointerIndexOfId(id));
      }
      break;
    case CEF_TET_RELEASED:
      if (GetPointerCount() == 1) {
        set_action(ui::MotionEvent::Action::UP);
      } else {
        set_action(ui::MotionEvent::Action::POINTER_UP);
        set_action_index(FindPointerIndexOfId(id));
      }
      break;
    case CEF_TET_CANCELLED:
      set_action(ui::MotionEvent::Action::CANCEL);
      break;
    case CEF_TET_MOVED:
      set_action(ui::MotionEvent::Action::MOVE);
      break;
  }
}

bool CefMotionEventOSR::IsValidIndex(int index) const {
  return (index >= 0) && (index < static_cast<int>(GetPointerCount()));
}

ui::PointerProperties CefMotionEventOSR::GetPointerPropertiesFromTouchEvent(
    const CefTouchEvent& touch,
    int id) {
  ui::PointerProperties pointer_properties;
  pointer_properties.x = touch.x;
  pointer_properties.y = touch.y;
  pointer_properties.raw_x = touch.x;
  pointer_properties.raw_y = touch.y;
  pointer_properties.id = id;
  pointer_properties.pressure = touch.pressure;
  pointer_properties.source_device_id = 0;

  pointer_properties.SetAxesAndOrientation(touch.radius_x, touch.radius_y,
                                           touch.rotation_angle);
  if (!pointer_properties.touch_major) {
    float default_size;
    switch (touch.pointer_type) {
      case CEF_POINTER_TYPE_PEN:
      case CEF_POINTER_TYPE_ERASER:
        // Default size for stylus events is 1x1.
        default_size = 1;
        break;
      default:
        default_size =
            2.f * ui::GestureConfiguration::GetInstance()->default_radius();
        break;
    }
    pointer_properties.touch_major = pointer_properties.touch_minor =
        default_size;
    pointer_properties.orientation = 0;
  }

  pointer_properties.tool_type =
      CefPointerTypeToMotionEventToolType(touch.pointer_type);

  return pointer_properties;
}
