// Copyright 2018 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.

// Copied with modifications from //ash/accessibility, refactored for use in
// chromecast.

#include "chromecast/browser/accessibility/touch_exploration_controller.h"

#include <utility>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event.h"
#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/geometry/rect.h"

#define SET_STATE(state) SetState(state, __func__)
#define VLOG_EVENT(event) \
  if (VLOG_IS_ON(1))      \
  VlogEvent(event, __func__)

namespace chromecast {
namespace shell {

namespace {

void SetTouchAccessibilityFlag(ui::Event* event) {
  // This flag is used to identify mouse move events that were generated from
  // touch exploration in Chrome code.
  event->set_flags(event->flags() | ui::EF_TOUCH_ACCESSIBILITY);
}

}  // namespace

TouchExplorationController::TouchExplorationController(
    aura::Window* root_window,
    TouchExplorationControllerDelegate* delegate,
    AccessibilitySoundDelegate* accessibility_sound_delegate)
    : root_window_(root_window),
      delegate_(delegate),
      accessibility_sound_delegate_(accessibility_sound_delegate),
      state_(NO_FINGERS_DOWN),
      anchor_point_state_(ANCHOR_POINT_NONE),
      gesture_provider_(new ui::GestureProviderAura(this, this)),
      prev_state_(NO_FINGERS_DOWN),
      VLOG_on_(true) {
}

TouchExplorationController::~TouchExplorationController() {
}

void TouchExplorationController::SetTouchAccessibilityAnchorPoint(
    const gfx::Point& anchor_point_dip) {
  gfx::Point native_point = anchor_point_dip;
  anchor_point_dip_ = gfx::PointF(native_point.x(), native_point.y());
  anchor_point_state_ = ANCHOR_POINT_EXPLICITLY_SET;
}

void TouchExplorationController::SetExcludeBounds(const gfx::Rect& bounds) {
  exclude_bounds_ = bounds;
}

ui::EventRewriteStatus TouchExplorationController::RewriteEvent(
    const ui::Event& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  if (!event.IsTouchEvent()) {
    if (event.IsKeyEvent()) {
      const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event);
      VLOG(1) << "\nKeyboard event: " << key_event.GetName()
              << "\n Key code: " << key_event.key_code()
              << ", Flags: " << key_event.flags()
              << ", Is char: " << key_event.is_char();
    }
    return ui::EVENT_REWRITE_CONTINUE;
  }
  const ui::TouchEvent& touch_event = static_cast<const ui::TouchEvent&>(event);

  if (event.type() == ui::ET_TOUCH_PRESSED)
    seen_press_ = true;

  // Touch events come through in screen pixels, but untransformed. This is the
  // raw coordinate not yet mapped to the root window's coordinate system or the
  // screen. Convert it into the root window's coordinate system, in DIP which
  // is what the rest of this class expects.
  gfx::Point location = touch_event.location();
  gfx::Point root_location = touch_event.root_location();
  root_window_->GetHost()->ConvertPixelsToDIP(&location);
  root_window_->GetHost()->ConvertPixelsToDIP(&root_location);

  if (!exclude_bounds_.IsEmpty()) {
    bool in_exclude_area = exclude_bounds_.Contains(location);
    if (in_exclude_area) {
      if (state_ == NO_FINGERS_DOWN)
        return ui::EVENT_REWRITE_CONTINUE;
      if (touch_event.type() == ui::ET_TOUCH_MOVED ||
          touch_event.type() == ui::ET_TOUCH_PRESSED) {
        return ui::EVENT_REWRITE_DISCARD;
      }
      // Otherwise, continue handling events. Basically, we want to let
      // CANCELLED or RELEASE events through so this can get back to
      // the NO_FINGERS_DOWN state.
    }
  }

  // If the tap timer should have fired by now but hasn't, run it now and
  // stop the timer. This is important so that behavior is consistent with
  // the timestamps of the events, and not dependent on the granularity of
  // the timer.
  if (tap_timer_.IsRunning() &&
      touch_event.time_stamp() - most_recent_press_timestamp_ >
          gesture_detector_config_.double_tap_timeout) {
    tap_timer_.Stop();
    OnTapTimerFired();
    // Note: this may change the state. We should now continue and process
    // this event under this new state.
  }

  if (passthrough_timer_.IsRunning() &&
      event.time_stamp() - most_recent_press_timestamp_ >
          gesture_detector_config_.longpress_timeout) {
    passthrough_timer_.Stop();
    OnPassthroughTimerFired();
  }

  const ui::EventType type = touch_event.type();
  const int touch_id = touch_event.pointer_details().id;

  // Always update touch ids and touch locations, so we can use those
  // no matter what state we're in.
  if (type == ui::ET_TOUCH_PRESSED) {
    current_touch_ids_.push_back(touch_id);
    touch_locations_.insert(std::pair<int, gfx::PointF>(touch_id, location));
  } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
    std::vector<int>::iterator it = std::find(
        current_touch_ids_.begin(), current_touch_ids_.end(), touch_id);

    // Can happen if touch exploration is enabled while fingers were down
    // or if an additional press occurred within the exclusion bounds.
    if (it == current_touch_ids_.end()) {
      // If we get a RELEASE event and we've never seen a PRESS event
      // since TouchExplorationController was instantiated, cancel the
      // event so that touch gestures that enable spoken feedback
      // don't accidentally trigger other behaviors on release.
      if (!seen_press_) {
        std::unique_ptr<ui::TouchEvent> new_event(new ui::TouchEvent(
            ui::ET_TOUCH_CANCELLED, gfx::Point(), touch_event.time_stamp(),
            touch_event.pointer_details()));
        new_event->set_location(location);
        new_event->set_root_location(root_location);
        new_event->set_flags(touch_event.flags());
        *rewritten_event = std::move(new_event);
        return ui::EVENT_REWRITE_REWRITTEN;
      }

      // Otherwise just pass it through.
      return ui::EVENT_REWRITE_CONTINUE;
    }

    current_touch_ids_.erase(it);
    touch_locations_.erase(touch_id);
  } else if (type == ui::ET_TOUCH_MOVED) {
    std::vector<int>::iterator it = std::find(
        current_touch_ids_.begin(), current_touch_ids_.end(), touch_id);

    // Can happen if touch exploration is enabled while fingers were down.
    if (it == current_touch_ids_.end())
      return ui::EVENT_REWRITE_CONTINUE;

    touch_locations_[*it] = gfx::PointF(location);
  } else {
    NOTREACHED() << "Unexpected event type received: " << event.GetName();
    return ui::EVENT_REWRITE_CONTINUE;
  }
  VLOG_EVENT(touch_event);

  // In order to avoid accidentally double tapping when moving off the edge
  // of the screen, the state will be rewritten to NoFingersDown.
  if ((type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) &&
      FindEdgesWithinInset(location, kLeavingScreenEdge) != NO_EDGE) {
    if (VLOG_on_)
      VLOG(1) << "Leaving screen";

    // Indicates to the user that they are leaving the screen.
    accessibility_sound_delegate_->PlayExitScreenEarcon();

    if (current_touch_ids_.size() == 0) {
      SET_STATE(NO_FINGERS_DOWN);
      if (VLOG_on_) {
        VLOG(1) << "Reset to no fingers in Rewrite event because the touch  "
                   "release or cancel was on the edge of the screen.";
      }
      return ui::EVENT_REWRITE_DISCARD;
    }
  }

  // We now need a TouchEvent that has its coordinates mapped into root window
  // DIP.
  ui::TouchEvent touch_event_dip = touch_event;
  touch_event_dip.set_location(location);

  // If the user is in a gesture state, or if there is a possiblity that the
  // user will enter it in the future, we send the event to the gesture
  // provider so it can keep track of the state of the fingers. When the user
  // leaves one of these states, SET_STATE will set the gesture provider to
  // NULL.
  if (gesture_provider_.get()) {
    if (gesture_provider_->OnTouchEvent(&touch_event_dip)) {
      gesture_provider_->OnTouchEventAck(
          touch_event_dip.unique_event_id(), false /* event_consumed */,
          false /* is_source_touch_event_set_non_blocking */);
    }
    ProcessGestureEvents();
  }

  ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE;
  // The rest of the processing depends on what state we're in.
  switch (state_) {
    case NO_FINGERS_DOWN:
      status = InNoFingersDown(touch_event_dip, rewritten_event);
      break;
    case SINGLE_TAP_PRESSED:
      status = InSingleTapPressed(touch_event_dip, rewritten_event);
      break;
    case SINGLE_TAP_RELEASED:
    case TOUCH_EXPLORE_RELEASED:
      status =
          InSingleTapOrTouchExploreReleased(touch_event_dip, rewritten_event);
      break;
    case DOUBLE_TAP_PENDING:
      status = InDoubleTapPending(touch_event_dip, rewritten_event);
      break;
    case TOUCH_RELEASE_PENDING:
      status = InTouchReleasePending(touch_event_dip, rewritten_event);
      break;
    case TOUCH_EXPLORATION:
      status = InTouchExploration(touch_event_dip, rewritten_event);
      break;
    case GESTURE_IN_PROGRESS:
      status = InGestureInProgress(touch_event_dip, rewritten_event);
      break;
    case TOUCH_EXPLORE_SECOND_PRESS:
      status = InTouchExploreSecondPress(touch_event_dip, rewritten_event);
      break;
    case ONE_FINGER_PASSTHROUGH:
      status = InOneFingerPassthrough(touch_event_dip, rewritten_event);
      break;
    case CORNER_PASSTHROUGH:
      status = InCornerPassthrough(touch_event_dip, rewritten_event);
      break;
    case WAIT_FOR_NO_FINGERS:
      status = InWaitForNoFingers(touch_event_dip, rewritten_event);
      break;
    case TWO_FINGER_TAP:
      status = InTwoFingerTap(touch_event_dip, rewritten_event);
      break;
    case EDGE_PASSTHROUGH:
      status = InEdgePassthrough(touch_event_dip, rewritten_event);
      break;
  }
  if (status == ui::EVENT_REWRITE_REWRITTEN) {
    DCHECK(rewritten_event->get());
    SetTouchAccessibilityFlag(rewritten_event->get());
  }
  return status;
}

ui::EventRewriteStatus TouchExplorationController::NextDispatchEvent(
    const ui::Event& last_event,
    std::unique_ptr<ui::Event>* new_event) {
  NOTREACHED();
  return ui::EVENT_REWRITE_CONTINUE;
}

ui::EventRewriteStatus TouchExplorationController::InNoFingersDown(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  const ui::EventType type = event.type();
  if (type != ui::ET_TOUCH_PRESSED) {
    NOTREACHED() << "Unexpected event type received: " << event.GetName();
    return ui::EVENT_REWRITE_CONTINUE;
  }

  int location = FindEdgesWithinInset(event.location(), kSlopDistanceFromEdge);
  // If the press was at a corner, the user might go into corner passthrough
  // instead.
  bool in_a_bottom_corner =
      (BOTTOM_LEFT_CORNER == location) || (BOTTOM_RIGHT_CORNER == location);
  if (in_a_bottom_corner) {
    passthrough_timer_.Start(
        FROM_HERE, gesture_detector_config_.longpress_timeout, this,
        &TouchExplorationController::OnPassthroughTimerFired);
  } else {
    // If the user enters the screen from the edge then send an earcon,
    // and enter passthrough mode so that the system gesture handle can
    // handle it.
    int edge = FindEdgesWithinInset(event.location(), kLeavingScreenEdge);
    if (edge != NO_EDGE) {
      accessibility_sound_delegate_->PlayEnterScreenEarcon();
      SET_STATE(EDGE_PASSTHROUGH);
      return ui::EVENT_REWRITE_CONTINUE;
    }
  }

  initial_press_ = std::make_unique<ui::TouchEvent>(event);
  most_recent_press_timestamp_ = initial_press_->time_stamp();
  initial_presses_[event.pointer_details().id] = event.location();
  last_unused_finger_event_ = std::make_unique<ui::TouchEvent>(event);
  StartTapTimer();
  SET_STATE(SINGLE_TAP_PRESSED);
  return ui::EVENT_REWRITE_DISCARD;
}

ui::EventRewriteStatus TouchExplorationController::InSingleTapPressed(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  const ui::EventType type = event.type();

  int location = FindEdgesWithinInset(event.location(), kMaxDistanceFromEdge);
  bool in_a_bottom_corner =
      (location == BOTTOM_LEFT_CORNER) || (location == BOTTOM_RIGHT_CORNER);
  // If the event is from the initial press and the location is no longer in the
  // corner, then we are not waiting for a corner passthrough anymore.
  if (event.pointer_details().id == initial_press_->pointer_details().id &&
      !in_a_bottom_corner) {
    if (passthrough_timer_.IsRunning()) {
      passthrough_timer_.Stop();
      // Since the long press timer has been running, it is possible that the
      // tap timer has timed out before the long press timer has. If the tap
      // timer timeout has elapsed, then fire the tap timer.
      if (event.time_stamp() - most_recent_press_timestamp_ >
          gesture_detector_config_.double_tap_timeout) {
        OnTapTimerFired();
      }
    }
  }

  if (type == ui::ET_TOUCH_PRESSED) {
    initial_presses_[event.pointer_details().id] = event.location();
    SET_STATE(TWO_FINGER_TAP);
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
    if (passthrough_timer_.IsRunning())
      passthrough_timer_.Stop();
    if (current_touch_ids_.size() == 0 &&
        event.pointer_details().id == initial_press_->pointer_details().id) {
      MaybeSendSimulatedTapInLiftActivationBounds(event);
      SET_STATE(SINGLE_TAP_RELEASED);
    } else if (current_touch_ids_.size() == 0) {
      SET_STATE(NO_FINGERS_DOWN);
    }
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_MOVED) {
    float distance = (event.location() - initial_press_->location()).Length();
    // If the user does not move far enough from the original position, then the
    // resulting movement should not be considered to be a deliberate gesture or
    // touch exploration.
    if (distance <= gesture_detector_config_.touch_slop)
      return ui::EVENT_REWRITE_DISCARD;

    float delta_time =
        (event.time_stamp() - most_recent_press_timestamp_).InSecondsF();
    float velocity = distance / delta_time;
    if (VLOG_on_) {
      VLOG(1) << "\n Delta time: " << delta_time << "\n Distance: " << distance
              << "\n Velocity of click: " << velocity
              << "\n Minimum swipe velocity: "
              << gesture_detector_config_.minimum_swipe_velocity;
    }

    // If the user moves fast enough from the initial touch location, start
    // gesture detection. Otherwise, jump to the touch exploration mode early.
    if (velocity > gesture_detector_config_.minimum_swipe_velocity) {
      SET_STATE(GESTURE_IN_PROGRESS);
      return InGestureInProgress(event, rewritten_event);
    }
    anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION;
    EnterTouchToMouseMode();
    SET_STATE(TOUCH_EXPLORATION);
    return InTouchExploration(event, rewritten_event);
  }
  NOTREACHED();
  return ui::EVENT_REWRITE_CONTINUE;
}

ui::EventRewriteStatus
TouchExplorationController::InSingleTapOrTouchExploreReleased(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  const ui::EventType type = event.type();
  // If there is more than one finger down, then discard to wait until no
  // fingers are down.
  if (current_touch_ids_.size() > 1) {
    SET_STATE(WAIT_FOR_NO_FINGERS);
    return ui::EVENT_REWRITE_DISCARD;
  }
  if (type == ui::ET_TOUCH_PRESSED) {
    // If there is no anchor point for synthesized events because the
    // user hasn't touch-explored or focused anything yet, we can't
    // send a click, so discard.
    if (anchor_point_state_ == ANCHOR_POINT_NONE) {
      tap_timer_.Stop();
      return ui::EVENT_REWRITE_DISCARD;
    }
    // This is the second tap in a double-tap (or double tap-hold).
    // We set the tap timer. If it fires before the user lifts their finger,
    // one-finger passthrough begins. Otherwise, there is a touch press and
    // release at the location of the last touch exploration.
    SET_STATE(DOUBLE_TAP_PENDING);
    // The old tap timer (from the initial click) is stopped if it is still
    // going, and the new one is set.
    tap_timer_.Stop();
    StartTapTimer();
    most_recent_press_timestamp_ = event.time_stamp();
    // This will update as the finger moves before a possible passthrough, and
    // will determine the offset.
    last_unused_finger_event_.reset(new ui::TouchEvent(event));
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_RELEASED &&
             anchor_point_state_ == ANCHOR_POINT_NONE) {
    // If the previous press was discarded, we need to also handle its
    // release.
    if (current_touch_ids_.size() == 0) {
      SET_STATE(NO_FINGERS_DOWN);
    }
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_MOVED) {
    return ui::EVENT_REWRITE_DISCARD;
  }
  NOTREACHED();
  return ui::EVENT_REWRITE_CONTINUE;
}

ui::EventRewriteStatus TouchExplorationController::InDoubleTapPending(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  const ui::EventType type = event.type();
  if (type == ui::ET_TOUCH_PRESSED) {
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_MOVED) {
    // If the user moves far enough from the initial touch location (outside
    // the "slop" region, jump to passthrough mode early.
    float delta = (event.location() - initial_press_->location()).Length();
    if (delta > gesture_detector_config_.double_tap_slop) {
      tap_timer_.Stop();
      OnTapTimerFired();
    }
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
    if (current_touch_ids_.size() != 0)
      return ui::EVENT_REWRITE_DISCARD;

    SendSimulatedClickOrTap();

    SET_STATE(NO_FINGERS_DOWN);
    return ui::EVENT_REWRITE_DISCARD;
  }
  NOTREACHED();
  return ui::EVENT_REWRITE_CONTINUE;
}

ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  const ui::EventType type = event.type();
  if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) {
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
    if (current_touch_ids_.size() != 0)
      return ui::EVENT_REWRITE_DISCARD;

    SendSimulatedClickOrTap();
    SET_STATE(NO_FINGERS_DOWN);
    return ui::EVENT_REWRITE_DISCARD;
  }
  NOTREACHED();
  return ui::EVENT_REWRITE_CONTINUE;
}

ui::EventRewriteStatus TouchExplorationController::InTouchExploration(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  const ui::EventType type = event.type();
  if (type == ui::ET_TOUCH_PRESSED) {
    // Enter split-tap mode.
    initial_press_ = std::make_unique<ui::TouchEvent>(event);
    tap_timer_.Stop();
    SET_STATE(TOUCH_EXPLORE_SECOND_PRESS);
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
    initial_press_ = std::make_unique<ui::TouchEvent>(event);
    StartTapTimer();
    most_recent_press_timestamp_ = event.time_stamp();
    MaybeSendSimulatedTapInLiftActivationBounds(event);
    SET_STATE(TOUCH_EXPLORE_RELEASED);
  } else if (type != ui::ET_TOUCH_MOVED) {
    NOTREACHED();
    return ui::EVENT_REWRITE_CONTINUE;
  }

  // Rewrite as a mouse-move event.
  // |event| locations are in DIP; see |RewriteEvent|. We need to dispatch
  // |screen coords.
  gfx::PointF location_f(ConvertDIPToScreenInPixels(event.location_f()));
  *rewritten_event = CreateMouseMoveEvent(location_f, event.flags());
  last_touch_exploration_ = std::make_unique<ui::TouchEvent>(event);
  if (anchor_point_state_ != ANCHOR_POINT_EXPLICITLY_SET)
    anchor_point_dip_ = last_touch_exploration_->location_f();

  return ui::EVENT_REWRITE_REWRITTEN;
}

ui::EventRewriteStatus TouchExplorationController::InGestureInProgress(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  // The events were sent to the gesture provider in RewriteEvent already.
  // If no gesture is registered before the tap timer times out, the state
  // will change to "wait for no fingers down" or "touch exploration" depending
  // on the number of fingers down, and this function will stop being called.
  if (current_touch_ids_.size() == 0) {
    SET_STATE(NO_FINGERS_DOWN);
  }
  return ui::EVENT_REWRITE_DISCARD;
}

ui::EventRewriteStatus TouchExplorationController::InCornerPassthrough(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  ui::EventType type = event.type();

  // If the first finger has left the corner, then exit passthrough.
  if (event.pointer_details().id == initial_press_->pointer_details().id) {
    int edges =
        FindEdgesWithinInset(event.location(), kSlopDistanceFromEdge);
    bool in_a_bottom_corner =
        (edges == BOTTOM_LEFT_CORNER) || (edges == BOTTOM_RIGHT_CORNER);
    if (type == ui::ET_TOUCH_MOVED && in_a_bottom_corner)
      return ui::EVENT_REWRITE_DISCARD;

    if (current_touch_ids_.size() == 0) {
      SET_STATE(NO_FINGERS_DOWN);
      return ui::EVENT_REWRITE_DISCARD;
    }
    SET_STATE(WAIT_FOR_NO_FINGERS);
    return ui::EVENT_REWRITE_DISCARD;
  }

  // |event| locations are in DIP; see |RewriteEvent|. We need to dispatch
  // screen coordinates.
  gfx::PointF location_f(ConvertDIPToScreenInPixels(event.location_f()));
  std::unique_ptr<ui::TouchEvent> new_event(new ui::TouchEvent(
      type, gfx::Point(), event.time_stamp(), event.pointer_details()));
  new_event->set_location_f(location_f);
  new_event->set_root_location_f(location_f);
  new_event->set_flags(event.flags());
  *rewritten_event = std::move(new_event);

  if (current_touch_ids_.size() == 0)
    SET_STATE(NO_FINGERS_DOWN);

  return ui::EVENT_REWRITE_REWRITTEN;
}

ui::EventRewriteStatus TouchExplorationController::InOneFingerPassthrough(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  if (event.pointer_details().id != initial_press_->pointer_details().id) {
    if (current_touch_ids_.size() == 0) {
      SET_STATE(NO_FINGERS_DOWN);
    }
    return ui::EVENT_REWRITE_DISCARD;
  }
  // |event| locations are in DIP; see |RewriteEvent|. We need to dispatch
  // screen coordinates.
  gfx::PointF location_f(
      ConvertDIPToScreenInPixels(event.location_f() - passthrough_offset_));
  std::unique_ptr<ui::TouchEvent> new_event(new ui::TouchEvent(
      event.type(), gfx::Point(), event.time_stamp(), event.pointer_details()));
  new_event->set_location_f(location_f);
  new_event->set_root_location_f(location_f);
  new_event->set_flags(event.flags());
  *rewritten_event = std::move(new_event);
  if (current_touch_ids_.size() == 0) {
    SET_STATE(NO_FINGERS_DOWN);
  }
  return ui::EVENT_REWRITE_REWRITTEN;
}

ui::EventRewriteStatus TouchExplorationController::InTouchExploreSecondPress(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  ui::EventType type = event.type();
  if (type == ui::ET_TOUCH_PRESSED) {
    // A third finger being pressed means that a split tap can no longer go
    // through. The user enters the wait state, Since there has already been
    // a press dispatched when split tap began, the touch needs to be
    // cancelled.
    std::unique_ptr<ui::TouchEvent> new_event(new ui::TouchEvent(
        ui::ET_TOUCH_CANCELLED, gfx::Point(), event.time_stamp(),
        initial_press_->pointer_details()));
    // TODO(dmazzoni): fix for multiple displays. http://crbug.com/616793
    // |event| locations are in DIP; see |RewriteEvent|. We need to dispatch
    // screen coordinates.
    gfx::PointF location_f(ConvertDIPToScreenInPixels(anchor_point_dip_));
    new_event->set_location_f(location_f);
    new_event->set_root_location_f(location_f);
    new_event->set_flags(event.flags());
    *rewritten_event = std::move(new_event);
    SET_STATE(WAIT_FOR_NO_FINGERS);
    return ui::EVENT_REWRITE_REWRITTEN;
  } else if (type == ui::ET_TOUCH_MOVED) {
    // If the fingers have moved too far from their original locations,
    // the user can no longer split tap.
    ui::TouchEvent* original_touch;
    if (event.pointer_details().id ==
        last_touch_exploration_->pointer_details().id) {
      original_touch = last_touch_exploration_.get();
    } else if (event.pointer_details().id ==
               initial_press_->pointer_details().id) {
      original_touch = initial_press_.get();
    } else {
      NOTREACHED();
      SET_STATE(WAIT_FOR_NO_FINGERS);
      return ui::EVENT_REWRITE_DISCARD;
    }
    // Check the distance between the current finger location and the original
    // location. The slop for this is a bit more generous since keeping two
    // fingers in place is a bit harder. If the user has left the slop, the
    // user enters the wait state.
    if ((event.location_f() - original_touch->location_f()).Length() >
        GetSplitTapTouchSlop()) {
      SET_STATE(WAIT_FOR_NO_FINGERS);
    }
    return ui::EVENT_REWRITE_DISCARD;
  } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) {
    // If the touch exploration finger is lifted, there is no option to return
    // to touch explore anymore. The remaining finger acts as a pending
    // tap or long tap for the last touch explore location.
    if (event.pointer_details().id ==
        last_touch_exploration_->pointer_details().id) {
      SET_STATE(TOUCH_RELEASE_PENDING);
      return ui::EVENT_REWRITE_DISCARD;
    }

    // Continue to release the touch only if the touch explore finger is the
    // only finger remaining.
    if (current_touch_ids_.size() != 1)
      return ui::EVENT_REWRITE_DISCARD;

    SendSimulatedClickOrTap();

    SET_STATE(TOUCH_EXPLORATION);
    EnterTouchToMouseMode();
    return ui::EVENT_REWRITE_DISCARD;
  }
  NOTREACHED();
  return ui::EVENT_REWRITE_CONTINUE;
}

ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  if (current_touch_ids_.size() == 0)
    SET_STATE(NO_FINGERS_DOWN);
  return ui::EVENT_REWRITE_DISCARD;
}

void TouchExplorationController::SendSimulatedClickOrTap() {
  // If we got an anchor point from ChromeVox, send a double-tap gesture
  // and let ChromeVox handle the click.
  if (anchor_point_state_ == ANCHOR_POINT_EXPLICITLY_SET) {
    delegate_->HandleAccessibilityGesture(ax::mojom::Gesture::kClick);
    return;
  }
  SendSimulatedTap();
}

void TouchExplorationController::SendSimulatedTap() {
  std::unique_ptr<ui::TouchEvent> touch_press;
  touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(),
                                       Now(),
                                       initial_press_->pointer_details()));
  touch_press->set_location_f(anchor_point_dip_);
  touch_press->set_root_location_f(anchor_point_dip_);
  DispatchEvent(touch_press.get());

  std::unique_ptr<ui::TouchEvent> touch_release;
  touch_release.reset(new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(),
                                         Now(),
                                         initial_press_->pointer_details()));
  touch_release->set_location_f(anchor_point_dip_);
  touch_release->set_root_location_f(anchor_point_dip_);
  DispatchEvent(touch_release.get());
}

void TouchExplorationController::MaybeSendSimulatedTapInLiftActivationBounds(
    const ui::TouchEvent& event) {
  gfx::Point location = event.location();
  gfx::Point anchor_location(anchor_point_dip_.x(), anchor_point_dip_.y());
  if (lift_activation_bounds_.Contains(anchor_location.x(),
                                       anchor_location.y()) &&
      lift_activation_bounds_.Contains(location)) {
    accessibility_sound_delegate_->PlayTouchTypeEarcon();
    SendSimulatedTap();
  }
}

ui::EventRewriteStatus TouchExplorationController::InTwoFingerTap(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  ui::EventType type = event.type();
  if (type == ui::ET_TOUCH_PRESSED) {
    // This is now a three finger gesture.
    SET_STATE(GESTURE_IN_PROGRESS);
    return ui::EVENT_REWRITE_DISCARD;
  }

  if (type == ui::ET_TOUCH_MOVED) {
    // Determine if it was a swipe.
    gfx::Point original_location = initial_presses_[event.pointer_details().id];
    float distance = (event.location() - original_location).Length();
    // If the user moves too far from the original position, consider the
    // movement a swipe.
    if (distance > gesture_detector_config_.touch_slop) {
      SET_STATE(GESTURE_IN_PROGRESS);
    }
    return ui::EVENT_REWRITE_DISCARD;
  }

  if (current_touch_ids_.size() != 0)
    return ui::EVENT_REWRITE_DISCARD;

  if (type == ui::ET_TOUCH_RELEASED) {
    delegate_->HandleAccessibilityGesture(ax::mojom::Gesture::kTap2);
    SET_STATE(NO_FINGERS_DOWN);
    return ui::EVENT_REWRITE_DISCARD;
  }
  return ui::EVENT_REWRITE_DISCARD;
}

ui::EventRewriteStatus TouchExplorationController::InEdgePassthrough(
    const ui::TouchEvent& event,
    std::unique_ptr<ui::Event>* rewritten_event) {
  if (current_touch_ids_.size() == 0) {
    SET_STATE(NO_FINGERS_DOWN);
  }
  // |event| locations are in DIP; see |RewriteEvent|. We need to dispatch
  // screen coordinates.
  gfx::PointF location_f(ConvertDIPToScreenInPixels(event.location_f()));
  std::unique_ptr<ui::TouchEvent> new_event(new ui::TouchEvent(
      event.type(), gfx::Point(), event.time_stamp(), event.pointer_details()));
  new_event->set_location_f(location_f);
  new_event->set_root_location_f(location_f);
  new_event->set_flags(event.flags());
  *rewritten_event = std::move(new_event);
  return ui::EVENT_REWRITE_REWRITTEN;
}

base::TimeTicks TouchExplorationController::Now() {
  return ui::EventTimeForNow();
}

void TouchExplorationController::StartTapTimer() {
  tap_timer_.Start(FROM_HERE, gesture_detector_config_.double_tap_timeout, this,
                   &TouchExplorationController::OnTapTimerFired);
}

void TouchExplorationController::OnTapTimerFired() {
  switch (state_) {
    case SINGLE_TAP_RELEASED:
      SET_STATE(NO_FINGERS_DOWN);
      break;
    case TOUCH_EXPLORE_RELEASED:
      SET_STATE(NO_FINGERS_DOWN);
      last_touch_exploration_ =
          std::make_unique<ui::TouchEvent>(*initial_press_);
      anchor_point_dip_ = last_touch_exploration_->location_f();
      anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION;
      return;
    case DOUBLE_TAP_PENDING: {
      SET_STATE(ONE_FINGER_PASSTHROUGH);
      passthrough_offset_ =
          last_unused_finger_event_->location_f() - anchor_point_dip_;
      std::unique_ptr<ui::TouchEvent> passthrough_press(
          new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), Now(),
                             last_unused_finger_event_->pointer_details()));
      passthrough_press->set_location_f(anchor_point_dip_);
      passthrough_press->set_root_location_f(anchor_point_dip_);
      DispatchEvent(passthrough_press.get());
      return;
    }
    case SINGLE_TAP_PRESSED:
      if (passthrough_timer_.IsRunning())
        return;
      FALLTHROUGH;
    case GESTURE_IN_PROGRESS:
      // If only one finger is down, go into touch exploration.
      if (current_touch_ids_.size() == 1) {
        anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION;
        EnterTouchToMouseMode();
        SET_STATE(TOUCH_EXPLORATION);
        break;
      }
      // Otherwise wait for all fingers to be lifted.
      SET_STATE(WAIT_FOR_NO_FINGERS);
      return;
    case TWO_FINGER_TAP:
      SET_STATE(WAIT_FOR_NO_FINGERS);
      break;
    default:
      return;
  }
  EnterTouchToMouseMode();
  std::unique_ptr<ui::Event> mouse_move = CreateMouseMoveEvent(
      initial_press_->location_f(), initial_press_->flags());
  DispatchEvent(mouse_move.get());
  last_touch_exploration_ = std::make_unique<ui::TouchEvent>(*initial_press_);
  anchor_point_dip_ = last_touch_exploration_->location_f();
  anchor_point_state_ = ANCHOR_POINT_FROM_TOUCH_EXPLORATION;
}

void TouchExplorationController::OnPassthroughTimerFired() {
  // The passthrough timer will only fire if if the user has held a finger in
  // one of the passthrough corners for the duration of the passthrough timeout.

  // Check that initial press isn't null. Also a check that if the initial
  // corner press was released, then it should not be in corner passthrough.
  if (!initial_press_ ||
      touch_locations_.find(initial_press_->pointer_details().id) !=
          touch_locations_.end()) {
  }

  gfx::Point location =
      ToRoundedPoint(touch_locations_[initial_press_->pointer_details().id]);
  int corner = FindEdgesWithinInset(location, kSlopDistanceFromEdge);
  if (corner != BOTTOM_LEFT_CORNER && corner != BOTTOM_RIGHT_CORNER)
    return;

  if (sound_timer_.IsRunning())
    sound_timer_.Stop();
  accessibility_sound_delegate_->PlayPassthroughEarcon();
  SET_STATE(CORNER_PASSTHROUGH);
  return;
}

void TouchExplorationController::DispatchEvent(ui::Event* event) {
  SetTouchAccessibilityFlag(event);
  if (event->IsLocatedEvent()) {
    ui::LocatedEvent* located_event = event->AsLocatedEvent();
    gfx::PointF screen_point(
        ConvertDIPToScreenInPixels(located_event->location_f()));
    located_event->set_location_f(screen_point);
    located_event->set_root_location_f(screen_point);
  }
  ignore_result(
      root_window_->GetHost()->dispatcher()->OnEventFromSource(event));
}

// This is an override for a function that is only called for timer-based events
// like long press. Events that are created synchronously as a result of
// certain touch events are added to the vector accessible via
// GetAndResetPendingGestures(). We only care about swipes (which are created
// synchronously), so we ignore this callback.
void TouchExplorationController::OnGestureEvent(ui::GestureConsumer* consumer,
                                                ui::GestureEvent* gesture) {}

void TouchExplorationController::ProcessGestureEvents() {
  std::vector<std::unique_ptr<ui::GestureEvent>> gestures =
      gesture_provider_->GetAndResetPendingGestures();
  bool resolved_gesture = false;
  max_gesture_touch_points_ =
      std::max(max_gesture_touch_points_, current_touch_ids_.size());
  for (const auto& gesture : gestures) {
    if (gesture->type() == ui::ET_GESTURE_SWIPE &&
        state_ == GESTURE_IN_PROGRESS) {
      OnSwipeEvent(gesture.get());
      // The tap timer to leave gesture state is ended, and we now wait for
      // all fingers to be released.
      tap_timer_.Stop();
      SET_STATE(WAIT_FOR_NO_FINGERS);
      return;
    }
  }

  if (resolved_gesture)
    return;

  if (current_touch_ids_.size() == 0) {
    switch (max_gesture_touch_points_) {
      case 3:
        delegate_->HandleAccessibilityGesture(ax::mojom::Gesture::kTap3);
        break;
      case 4:
        delegate_->HandleAccessibilityGesture(ax::mojom::Gesture::kTap4);
        break;
      default:
        break;
    }
    max_gesture_touch_points_ = 0;
  }
}

void TouchExplorationController::OnSwipeEvent(ui::GestureEvent* swipe_gesture) {
  // A swipe gesture contains details for the direction in which the swipe
  // occurred. TODO(evy) : Research which swipe results users most want and
  // remap these swipes to the best events. Hopefully in the near future
  // there will also be a menu for users to pick custom mappings.
  ui::GestureEventDetails event_details = swipe_gesture->details();
  int num_fingers = event_details.touch_points();
  if (VLOG_on_)
    VLOG(1) << "\nSwipe with " << num_fingers << " fingers.";

  ax::mojom::Gesture gesture = ax::mojom::Gesture::kNone;
  if (event_details.swipe_left()) {
    switch (num_fingers) {
      case 1:
        gesture = ax::mojom::Gesture::kSwipeLeft1;
        break;
      case 2:
        gesture = ax::mojom::Gesture::kSwipeLeft2;
        break;
      case 3:
        gesture = ax::mojom::Gesture::kSwipeLeft3;
        break;
      case 4:
        gesture = ax::mojom::Gesture::kSwipeLeft4;
        break;
      default:
        break;
    }
  } else if (event_details.swipe_up()) {
    switch (num_fingers) {
      case 1:
        gesture = ax::mojom::Gesture::kSwipeUp1;
        break;
      case 2:
        gesture = ax::mojom::Gesture::kSwipeUp2;
        break;
      case 3:
        gesture = ax::mojom::Gesture::kSwipeUp3;
        break;
      case 4:
        gesture = ax::mojom::Gesture::kSwipeUp4;
        break;
      default:
        break;
    }
  } else if (event_details.swipe_right()) {
    switch (num_fingers) {
      case 1:
        gesture = ax::mojom::Gesture::kSwipeRight1;
        break;
      case 2:
        gesture = ax::mojom::Gesture::kSwipeRight2;
        break;
      case 3:
        gesture = ax::mojom::Gesture::kSwipeRight3;
        break;
      case 4:
        gesture = ax::mojom::Gesture::kSwipeRight4;
        break;
      default:
        break;
    }
  } else if (event_details.swipe_down()) {
    switch (num_fingers) {
      case 1:
        gesture = ax::mojom::Gesture::kSwipeDown1;
        break;
      case 2:
        gesture = ax::mojom::Gesture::kSwipeDown2;
        break;
      case 3:
        gesture = ax::mojom::Gesture::kSwipeDown3;
        break;
      case 4:
        gesture = ax::mojom::Gesture::kSwipeDown4;
        break;
      default:
        break;
    }
  }

  if (gesture != ax::mojom::Gesture::kNone)
    delegate_->HandleAccessibilityGesture(gesture);
}

int TouchExplorationController::FindEdgesWithinInset(gfx::Point point_dip,
                                                     float inset) {
  gfx::RectF inner_bounds_dip(root_window_->bounds());
  inner_bounds_dip.Inset(inset, inset);

  // Bitwise manipulation in order to determine where on the screen the point
  // lies. If more than one bit is turned on, then it is a corner where the two
  // bit/edges intersect. Otherwise, if no bits are turned on, the point must be
  // in the center of the screen.
  int result = NO_EDGE;
  if (point_dip.x() < inner_bounds_dip.x())
    result |= LEFT_EDGE;
  if (point_dip.x() > inner_bounds_dip.right())
    result |= RIGHT_EDGE;
  if (point_dip.y() < inner_bounds_dip.y())
    result |= TOP_EDGE;
  if (point_dip.y() > inner_bounds_dip.bottom())
    result |= BOTTOM_EDGE;
  return result;
}

void TouchExplorationController::DispatchKeyWithFlags(
    const ui::KeyboardCode key,
    int flags) {
  ui::KeyEvent key_down(ui::ET_KEY_PRESSED, key, flags);
  ui::KeyEvent key_up(ui::ET_KEY_RELEASED, key, flags);
  DispatchEvent(&key_down);
  DispatchEvent(&key_up);
  if (VLOG_on_) {
    VLOG(1) << "\nKey down: key code : " << key_down.key_code()
            << ", flags: " << key_down.flags()
            << "\nKey up: key code : " << key_up.key_code()
            << ", flags: " << key_up.flags();
  }
}

base::OnceClosure TouchExplorationController::BindKeyEventWithFlags(
    const ui::KeyboardCode key,
    int flags) {
  return base::BindOnce(&TouchExplorationController::DispatchKeyWithFlags,
                        base::Unretained(this), key, flags);
}

std::unique_ptr<ui::MouseEvent>
TouchExplorationController::CreateMouseMoveEvent(const gfx::PointF& location,
                                                 int flags) {
  // The "synthesized" flag should be set on all events that don't have a
  // backing native event.
  flags |= ui::EF_IS_SYNTHESIZED;

  // TODO(dmazzoni) http://crbug.com/391008 - get rid of this hack.
  // This is a short-term workaround for the limitation that we're using
  // the ChromeVox content script to process touch exploration events, but
  // ChromeVox needs a way to distinguish between a real mouse move and a
  // mouse move generated from touch exploration, so we have touch exploration
  // pretend that the command key was down (which becomes the "meta" key in
  // JavaScript). We can remove this hack when the ChromeVox content script
  // goes away and native accessibility code sends a touch exploration
  // event to the new ChromeVox background page via the automation api.
  flags |= ui::EF_COMMAND_DOWN;

  std::unique_ptr<ui::MouseEvent> event(new ui::MouseEvent(
      ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), Now(), flags, 0));
  event->set_location_f(location);
  event->set_root_location_f(location);
  return event;
}

void TouchExplorationController::EnterTouchToMouseMode() {
  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(root_window_);
  if (cursor_client && !cursor_client->IsMouseEventsEnabled())
    cursor_client->EnableMouseEvents();
  if (cursor_client && cursor_client->IsCursorVisible())
    cursor_client->HideCursor();
}

void TouchExplorationController::SetState(State new_state,
                                          const char* function_name) {
  state_ = new_state;
  VlogState(function_name);
  // These are the states the user can be in that will never result in a
  // gesture before the user returns to NO_FINGERS_DOWN. Therefore, if the
  // gesture provider still exists, it's reset to NULL until the user returns
  // to NO_FINGERS_DOWN.
  switch (new_state) {
    case SINGLE_TAP_RELEASED:
    case TOUCH_EXPLORE_RELEASED:
    case DOUBLE_TAP_PENDING:
    case TOUCH_RELEASE_PENDING:
    case TOUCH_EXPLORATION:
    case TOUCH_EXPLORE_SECOND_PRESS:
    case ONE_FINGER_PASSTHROUGH:
    case CORNER_PASSTHROUGH:
    case WAIT_FOR_NO_FINGERS:
    case EDGE_PASSTHROUGH:
      if (gesture_provider_.get())
        gesture_provider_.reset(NULL);
      max_gesture_touch_points_ = 0;
      break;
    case NO_FINGERS_DOWN:
      gesture_provider_ = std::make_unique<ui::GestureProviderAura>(this, this);
      if (sound_timer_.IsRunning())
        sound_timer_.Stop();
      tap_timer_.Stop();
      break;
    case SINGLE_TAP_PRESSED:
    case GESTURE_IN_PROGRESS:
    case TWO_FINGER_TAP:
      break;
  }
}

void TouchExplorationController::VlogState(const char* function_name) {
  if (!VLOG_on_)
    return;
  if (prev_state_ == state_)
    return;
  prev_state_ = state_;
  const char* state_string = EnumStateToString(state_);
  VLOG(1) << "\n Function name: " << function_name
          << "\n State: " << state_string;
}

void TouchExplorationController::VlogEvent(const ui::TouchEvent& touch_event,
                                           const char* function_name) {
  if (!VLOG_on_)
    return;

  if (prev_event_ && prev_event_->type() == touch_event.type() &&
      prev_event_->pointer_details().id == touch_event.pointer_details().id) {
    return;
  }
  // The above statement prevents events of the same type and id from being
  // printed in a row. However, if two fingers are down, they would both be
  // moving and alternating printing move events unless we check for this.
  if (prev_event_ && prev_event_->type() == ui::ET_TOUCH_MOVED &&
      touch_event.type() == ui::ET_TOUCH_MOVED) {
    return;
  }

  const std::string& type = touch_event.GetName();
  const gfx::PointF& location = touch_event.location_f();
  const int touch_id = touch_event.pointer_details().id;

  VLOG(1) << "\n Function name: " << function_name << "\n Event Type: " << type
          << "\n Location: " << location.ToString()
          << "\n Touch ID: " << touch_id;
  prev_event_ = std::make_unique<ui::TouchEvent>(touch_event);
}

const char* TouchExplorationController::EnumStateToString(State state) {
  switch (state) {
    case NO_FINGERS_DOWN:
      return "NO_FINGERS_DOWN";
    case SINGLE_TAP_PRESSED:
      return "SINGLE_TAP_PRESSED";
    case SINGLE_TAP_RELEASED:
      return "SINGLE_TAP_RELEASED";
    case TOUCH_EXPLORE_RELEASED:
      return "TOUCH_EXPLORE_RELEASED";
    case DOUBLE_TAP_PENDING:
      return "DOUBLE_TAP_PENDING";
    case TOUCH_RELEASE_PENDING:
      return "TOUCH_RELEASE_PENDING";
    case TOUCH_EXPLORATION:
      return "TOUCH_EXPLORATION";
    case GESTURE_IN_PROGRESS:
      return "GESTURE_IN_PROGRESS";
    case TOUCH_EXPLORE_SECOND_PRESS:
      return "TOUCH_EXPLORE_SECOND_PRESS";
    case CORNER_PASSTHROUGH:
      return "CORNER_PASSTHROUGH";
    case ONE_FINGER_PASSTHROUGH:
      return "ONE_FINGER_PASSTHROUGH";
    case WAIT_FOR_NO_FINGERS:
      return "WAIT_FOR_NO_FINGERS";
    case TWO_FINGER_TAP:
      return "TWO_FINGER_TAP";
    case EDGE_PASSTHROUGH:
      return "EDGE_PASSTHROUGH";
  }
  return "Not a state";
}

float TouchExplorationController::GetSplitTapTouchSlop() {
  return gesture_detector_config_.touch_slop * 3;
}

gfx::PointF TouchExplorationController::ConvertDIPToScreenInPixels(
    const gfx::PointF& location_f) {
  gfx::Point location(gfx::ToFlooredPoint(location_f));
  root_window_->GetHost()->ConvertDIPToScreenInPixels(&location);
  return gfx::PointF(location);
}

}  // namespace shell
}  // namespace chromecast
