// Copyright (c) 2012 The Chromium OS 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 "gestures/include/immediate_interpreter.h"

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <limits>
#include <tuple>

#include "gestures/include/gestures.h"
#include "gestures/include/logging.h"
#include "gestures/include/util.h"

using std::bind1st;
using std::for_each;
using std::make_pair;
using std::make_tuple;
using std::max;
using std::mem_fun;
using std::min;
using std::tuple;

namespace gestures {

namespace {

float MaxMag(float a, float b) {
  if (fabsf(a) > fabsf(b))
    return a;
  return b;
}
float MinMag(float a, float b) {
  if (fabsf(a) < fabsf(b))
    return a;
  return b;
}

// A comparator class for use with STL algorithms that sorts FingerStates
// by their origin timestamp.
class FingerOriginCompare {
 public:
  explicit FingerOriginCompare(const ImmediateInterpreter* interpreter)
      : interpreter_(interpreter) {
  }
  bool operator() (const FingerState* a, const FingerState* b) const {
    return interpreter_->finger_origin_timestamp(a->tracking_id) <
           interpreter_->finger_origin_timestamp(b->tracking_id);
  }

 private:
  const ImmediateInterpreter* interpreter_;
};

}  // namespace {}

void TapRecord::NoteTouch(short the_id, const FingerState& fs) {
  // New finger must be close enough to an existing finger
  if (!touched_.empty()) {
    bool reject_new_finger = true;
    for (map<short, FingerState, kMaxTapFingers>::const_iterator it =
             touched_.begin(), e = touched_.end(); it != e; ++it) {
      const FingerState& existing_fs = (*it).second;
      if (immediate_interpreter_->metrics_->CloseEnoughToGesture(
              Vector2(existing_fs),
              Vector2(fs))) {
        reject_new_finger = false;
        break;
      }
    }
    if (reject_new_finger)
      return;
  }
  touched_[the_id] = fs;
}

void TapRecord::NoteRelease(short the_id) {
  if (touched_.find(the_id) != touched_.end())
    released_.insert(the_id);
}

void TapRecord::Remove(short the_id) {
  min_tap_pressure_met_.erase(the_id);
  min_cotap_pressure_met_.erase(the_id);
  touched_.erase(the_id);
  released_.erase(the_id);
}

float TapRecord::CotapMinPressure() const {
  return immediate_interpreter_->tap_min_pressure() * 0.5;
}

void TapRecord::Update(const HardwareState& hwstate,
                       const HardwareState& prev_hwstate,
                       const set<short, kMaxTapFingers>& added,
                       const set<short, kMaxTapFingers>& removed,
                       const set<short, kMaxFingers>& dead) {
  if (!t5r2_ && (hwstate.finger_cnt != hwstate.touch_cnt ||
                 prev_hwstate.finger_cnt != prev_hwstate.touch_cnt)) {
    // switch to T5R2 mode
    t5r2_ = true;
    t5r2_touched_size_ = touched_.size();
    t5r2_released_size_ = released_.size();
  }
  if (t5r2_) {
    short diff = static_cast<short>(hwstate.touch_cnt) -
        static_cast<short>(prev_hwstate.touch_cnt);
    if (diff > 0)
      t5r2_touched_size_ += diff;
    else if (diff < 0)
      t5r2_released_size_ += -diff;
  }
  for (set<short, kMaxTapFingers>::const_iterator it = added.begin(),
           e = added.end(); it != e; ++it)
    Log("TapRecord::Update: Added: %d", *it);
  for (set<short, kMaxTapFingers>::const_iterator it = removed.begin(),
           e = removed.end(); it != e; ++it)
    Log("TapRecord::Update: Removed: %d", *it);
  for (set<short, kMaxFingers>::const_iterator it = dead.begin(),
           e = dead.end(); it != e; ++it)
    Log("TapRecord::Update: Dead: %d", *it);
  for_each(dead.begin(), dead.end(),
           bind1st(mem_fun(&TapRecord::Remove), this));
  for (set<short, kMaxTapFingers>::const_iterator it = added.begin(),
           e = added.end(); it != e; ++it)
    NoteTouch(*it, *hwstate.GetFingerState(*it));
  for_each(removed.begin(), removed.end(),
           bind1st(mem_fun(&TapRecord::NoteRelease), this));
  // Check if min tap/cotap pressure met yet
  const float cotap_min_pressure = CotapMinPressure();
  for (map<short, FingerState, kMaxTapFingers>::iterator it =
           touched_.begin(), e = touched_.end();
       it != e; ++it) {
    const FingerState* fs = hwstate.GetFingerState((*it).first);
    if (fs) {
      if (fs->pressure >= immediate_interpreter_->tap_min_pressure())
        min_tap_pressure_met_.insert(fs->tracking_id);
      if (fs->pressure >= cotap_min_pressure) {
        min_cotap_pressure_met_.insert(fs->tracking_id);
        if ((*it).second.pressure < cotap_min_pressure) {
          // Update existing record, since the old one hadn't met the cotap
          // pressure
          (*it).second = *fs;
        }
      }
      stime_t finger_age = hwstate.timestamp -
          immediate_interpreter_->finger_origin_timestamp(fs->tracking_id);
      if (finger_age > immediate_interpreter_->tap_max_finger_age())
        fingers_below_max_age_ = false;
    }
  }
}

void TapRecord::Clear() {
  min_tap_pressure_met_.clear();
  min_cotap_pressure_met_.clear();
  t5r2_ = false;
  t5r2_touched_size_ = 0;
  t5r2_released_size_ = 0;
  fingers_below_max_age_ = true;
  touched_.clear();
  released_.clear();
}

bool TapRecord::Moving(const HardwareState& hwstate,
                       const float dist_max) const {
  const float cotap_min_pressure = CotapMinPressure();
  for (map<short, FingerState, kMaxTapFingers>::const_iterator it =
           touched_.begin(), e = touched_.end(); it != e; ++it) {
    const FingerState* fs = hwstate.GetFingerState((*it).first);
    if (!fs)
      continue;
    // Only look for moving when current frame meets cotap pressure and
    // our history contains a contact that's met cotap pressure.
    if (fs->pressure < cotap_min_pressure ||
        (*it).second.pressure < cotap_min_pressure)
      continue;
    // Compute distance moved
    float dist_x = fs->position_x - (*it).second.position_x;
    float dist_y = fs->position_y - (*it).second.position_y;
    // Respect WARP flags
    if (fs->flags & GESTURES_FINGER_WARP_X_TAP_MOVE)
      dist_x = 0.0;
    if (fs->flags & GESTURES_FINGER_WARP_X_TAP_MOVE)
      dist_y = 0.0;

    bool moving =
        dist_x * dist_x + dist_y * dist_y > dist_max * dist_max;
    if (moving)
      return true;
  }
  return false;
}

bool TapRecord::Motionless(const HardwareState& hwstate, const HardwareState&
                           prev_hwstate, const float max_speed) const {
  const float cotap_min_pressure = CotapMinPressure();
  for (map<short, FingerState, kMaxTapFingers>::const_iterator it =
           touched_.begin(), e = touched_.end(); it != e; ++it) {
    const FingerState* fs = hwstate.GetFingerState((*it).first);
    const FingerState* prev_fs = prev_hwstate.GetFingerState((*it).first);
    if (!fs || !prev_fs)
      continue;
    // Only look for moving when current frame meets cotap pressure and
    // our history contains a contact that's met cotap pressure.
    if (fs->pressure < cotap_min_pressure ||
        prev_fs->pressure < cotap_min_pressure)
      continue;
    // Compute distance moved
    if (DistSq(*fs, *prev_fs) > max_speed * max_speed)
      return false;
  }
  return true;
}

bool TapRecord::TapBegan() const {
  if (t5r2_)
    return t5r2_touched_size_ > 0;
  return !touched_.empty();
}

bool TapRecord::TapComplete() const {
  bool ret = false;
  if (t5r2_)
    ret = t5r2_touched_size_ && t5r2_touched_size_ == t5r2_released_size_;
  else
    ret = !touched_.empty() && (touched_.size() == released_.size());
  for (map<short, FingerState, kMaxTapFingers>::const_iterator
           it = touched_.begin(), e = touched_.end(); it != e; ++it)
    Log("TapRecord::TapComplete: touched_: %d", (*it).first);
  for (set<short, kMaxTapFingers>::const_iterator it = released_.begin(),
           e = released_.end(); it != e; ++it)
    Log("TapRecord::TapComplete: released_: %d", *it);
  return ret;
}

bool TapRecord::MinTapPressureMet() const {
  // True if any touching finger met minimum pressure
  return t5r2_ || !min_tap_pressure_met_.empty();
}

bool TapRecord::FingersBelowMaxAge() const {
  return fingers_below_max_age_;
}

int TapRecord::TapType() const {
  size_t touched_size =
      t5r2_ ? t5r2_touched_size_ : min_cotap_pressure_met_.size();
  int ret = GESTURES_BUTTON_LEFT;
  if (touched_size > 1)
    ret = GESTURES_BUTTON_RIGHT;
  if (touched_size == 3 &&
      immediate_interpreter_->three_finger_click_enable_.val_ &&
      (!t5r2_ || immediate_interpreter_->t5r2_three_finger_click_enable_.val_))
    ret = GESTURES_BUTTON_MIDDLE;
  return ret;
}

// static
ScrollEvent ScrollEvent::Add(const ScrollEvent& evt_a,
                             const ScrollEvent& evt_b) {
  ScrollEvent ret = { evt_a.dx + evt_b.dx,
                      evt_a.dy + evt_b.dy,
                      evt_a.dt + evt_b.dt };
  return ret;
}

void ScrollEventBuffer::Insert(float dx, float dy, float dt) {
  head_ = (head_ + max_size_ - 1) % max_size_;
  buf_[head_].dx = dx;
  buf_[head_].dy = dy;
  buf_[head_].dt = dt;
  size_ = std::min(size_ + 1, max_size_);
}

void ScrollEventBuffer::Clear() {
  size_ = 0;
}

const ScrollEvent& ScrollEventBuffer::Get(size_t offset) const {
  if (offset >= size_) {
    Err("Out of bounds access!");
    // avoid returning null pointer
    static ScrollEvent dummy_event = { 0.0, 0.0, 0.0 };
    return dummy_event;
  }
  return buf_[(head_ + offset) % max_size_];
}

void ScrollEventBuffer::GetSpeedSq(size_t num_events, float* dist_sq,
                                   float* dt) const {
  float dx = 0.0;
  float dy = 0.0;
  *dt = 0.0;
  for (size_t i = 0; i < Size() && i < num_events; i++) {
    const ScrollEvent& evt = Get(i);
    dx += evt.dx;
    dy += evt.dy;
    *dt += evt.dt;
  }
  *dist_sq = dx * dx + dy * dy;
}

HardwareStateBuffer::HardwareStateBuffer(size_t size)
    : states_(new HardwareState[size]),
      newest_index_(0), size_(size), max_finger_cnt_(0) {
  for (size_t i = 0; i < size_; i++) {
    memset(&states_[i], 0, sizeof(HardwareState));
  }
}

HardwareStateBuffer::~HardwareStateBuffer() {
  for (size_t i = 0; i < size_; i++) {
    delete[] states_[i].fingers;
  }
}

void HardwareStateBuffer::Reset(size_t max_finger_cnt) {
  max_finger_cnt_ = max_finger_cnt;
  for (size_t i = 0; i < size_; i++) {
    delete[] states_[i].fingers;
  }
  if (max_finger_cnt_) {
    for (size_t i = 0; i < size_; i++) {
      states_[i].fingers = new FingerState[max_finger_cnt_];
      memset(states_[i].fingers, 0, sizeof(FingerState) * max_finger_cnt_);
    }
  } else {
    for (size_t i = 0; i < size_; i++) {
      states_[i].fingers = NULL;
    }
  }
}

void HardwareStateBuffer::PushState(const HardwareState& state) {
  newest_index_ = (newest_index_ + size_ - 1) % size_;
  Get(0)->DeepCopy(state, max_finger_cnt_);
}

void HardwareStateBuffer::PopState() {
  newest_index_ = (newest_index_ + 1) % size_;
}

ScrollManager::ScrollManager(PropRegistry* prop_reg)
    : prev_result_suppress_finger_movement_(false),
      did_generate_scroll_(false),
      max_stationary_move_speed_(prop_reg, "Max Stationary Move Speed", 0.0),
      max_stationary_move_speed_hysteresis_(
          prop_reg, "Max Stationary Move Speed Hysteresis", 0.0),
      max_stationary_move_suppress_distance_(
          prop_reg, "Max Stationary Move Suppress Distance", 1.0),
      max_pressure_change_(prop_reg, "Max Allowed Pressure Change Per Sec",
                           800.0),
      max_pressure_change_hysteresis_(prop_reg,
                                      "Max Hysteresis Pressure Per Sec",
                                      600.0),
      min_scroll_dead_reckoning_(prop_reg,
                                 "Min Scroll Dead Reckoning Distance",
                                 0.0),
      max_pressure_change_duration_(prop_reg,
                                    "Max Pressure Change Duration",
                                    0.016),
      max_stationary_speed_(prop_reg, "Max Finger Stationary Speed", 0.0),
      vertical_scroll_snap_slope_(prop_reg, "Vertical Scroll Snap Slope",
                                  tanf(DegToRad(50.0))),  // 50 deg. from horiz.
      horizontal_scroll_snap_slope_(prop_reg, "Horizontal Scroll Snap Slope",
                                    tanf(DegToRad(30.0))),

      fling_buffer_depth_(prop_reg, "Fling Buffer Depth", 10),
      fling_buffer_suppress_zero_length_scrolls_(
          prop_reg, "Fling Buffer Suppress Zero Length Scrolls", 1),
      fling_buffer_min_avg_speed_(prop_reg,
                                  "Fling Buffer Min Avg Speed",
                                  10.0) {
}

bool ScrollManager::StationaryFingerPressureChangingSignificantly(
    const HardwareStateBuffer& state_buffer,
    const FingerState& current) const {
  bool pressure_is_increasing = false;
  bool pressure_direction_established = false;
  const FingerState* prev = &current;
  stime_t now = state_buffer.Get(0)->timestamp;
  stime_t duration = 0.0;

  if (max_pressure_change_duration_.val_ > 0.0) {
    for (size_t i = 1; i < state_buffer.Size(); i++) {
      const HardwareState& state = *state_buffer.Get(i);
      stime_t local_duration = now - state.timestamp;
      if (local_duration > max_pressure_change_duration_.val_)
        break;

      duration = local_duration;
      const FingerState* fs = state.GetFingerState(current.tracking_id);
      // If the finger just appeared, skip to check pressure change then
      if (!fs)
        break;

      float pressure_difference = prev->pressure - fs->pressure;
      if (pressure_difference) {
        bool is_currently_increasing = pressure_difference > 0.0;
        if (!pressure_direction_established) {
          pressure_is_increasing = is_currently_increasing;
          pressure_direction_established = true;
        }

        // If pressure changes are unstable, it's likely just noise.
        if (is_currently_increasing != pressure_is_increasing)
          return false;
      }
      prev = fs;
    }
  } else {
    // To disable this feature, max_pressure_change_duration_ can be set to a
    // negative number.  When this occurs it reverts to just checking the last
    // event, not looking through the backlog as well.
    prev = state_buffer.Get(1)->GetFingerState(current.tracking_id);
    duration = now - state_buffer.Get(1)->timestamp;
  }

  if (max_stationary_speed_.val_ != 0.0) {
    // If finger moves too fast, we don't consider it stationary.
    float dist_sq = (current.position_x - prev->position_x) *
                    (current.position_x - prev->position_x) +
                    (current.position_y - prev->position_y) *
                    (current.position_y - prev->position_y);
    float dist_sq_thresh = duration * duration *
        max_stationary_speed_.val_ * max_stationary_speed_.val_;
    if (dist_sq > dist_sq_thresh)
      return false;
  }

  float dp_thresh = duration *
      (prev_result_suppress_finger_movement_ ?
       max_pressure_change_hysteresis_.val_ :
       max_pressure_change_.val_);
  float dp = fabsf(current.pressure - prev->pressure);
  return dp > dp_thresh;
}

bool ScrollManager::ComputeScroll(
    const HardwareStateBuffer& state_buffer,
    const FingerMap& prev_gs_fingers,
    const FingerMap& gs_fingers,
    GestureType prev_gesture_type,
    const Gesture& prev_result,
    Gesture* result,
    ScrollEventBuffer* scroll_buffer) {
  // For now, we take the movement of the biggest moving finger.
  float max_mag_sq = 0.0;  // square of max mag
  float dx = 0.0;
  float dy = 0.0;
  bool suppress_finger_movement = false;
  for (FingerMap::const_iterator it =
           gs_fingers.begin(), e = gs_fingers.end(); it != e; ++it) {
    const FingerState* fs = state_buffer.Get(0)->GetFingerState(*it);
    const FingerState* prev = state_buffer.Get(1)->GetFingerState(*it);
    if (!prev)
      return false;
    const stime_t dt =
        state_buffer.Get(0)->timestamp - state_buffer.Get(1)->timestamp;
    // Call SuppressStationaryFingerMovement even if suppress_finger_movement
    // is already true, b/c it records updates.
    suppress_finger_movement =
        SuppressStationaryFingerMovement(*fs, *prev, dt) ||
        suppress_finger_movement ||
        StationaryFingerPressureChangingSignificantly(state_buffer, *fs);
    float local_dx = fs->position_x - prev->position_x;
    if (fs->flags & GESTURES_FINGER_WARP_X_NON_MOVE)
      local_dx = 0.0;
    float local_dy = fs->position_y - prev->position_y;
    if (fs->flags & GESTURES_FINGER_WARP_Y_NON_MOVE)
      local_dy = 0.0;
    float local_max_mag_sq = local_dx * local_dx + local_dy * local_dy;
    if (local_max_mag_sq > max_mag_sq) {
      max_mag_sq = local_max_mag_sq;
      dx = local_dx;
      dy = local_dy;
    }
  }

  // See if we should snap to vertical/horizontal
  if (fabsf(dy) < horizontal_scroll_snap_slope_.val_ * fabsf(dx))
    dy = 0.0;  // snap to horizontal
  else if (fabsf(dy) > vertical_scroll_snap_slope_.val_ * fabsf(dx))
    dx = 0.0;  // snap to vertical

  prev_result_suppress_finger_movement_ = suppress_finger_movement;
  if (suppress_finger_movement) {
    // If we get here, it means that the pressure of the finger causing
    // the scroll is changing a lot, so we don't trust it. It's likely
    // leaving the touchpad. Normally we might just do nothing, but having
    // a frame or two of 0 length scroll before a fling looks janky. We
    // could also just start the fling now, but we don't want to do that
    // because the fingers may not actually be leaving. What seems to work
    // well is sort of dead-reckoning approach where we just repeat the
    // scroll event from the previous input frame.
    // Since this isn't a "real" scroll event, we don't put it into
    // scroll_buffer_.
    // Also, only use previous gesture if it's in the same direction.
    if (prev_result.type == kGestureTypeScroll &&
        prev_result.details.scroll.dy * dy >= 0 &&
        prev_result.details.scroll.dx * dx >= 0 &&
        (fabsf(prev_result.details.scroll.dy) >=
         min_scroll_dead_reckoning_.val_ ||
         fabsf(prev_result.details.scroll.dx) >=
         min_scroll_dead_reckoning_.val_)) {
      did_generate_scroll_ = true;
      *result = prev_result;
    } else if (min_scroll_dead_reckoning_.val_ > 0.0) {
      scroll_buffer->Clear();
    }
    return false;
  }

  if (max_mag_sq > 0) {
    did_generate_scroll_ = true;
    *result = Gesture(kGestureScroll,
                      state_buffer.Get(1)->timestamp,
                      state_buffer.Get(0)->timestamp,
                      dx, dy);
  }
  if (prev_gesture_type != kGestureTypeScroll || prev_gs_fingers != gs_fingers)
    scroll_buffer->Clear();
  if (!fling_buffer_suppress_zero_length_scrolls_.val_ ||
      !FloatEq(dx, 0.0) || !FloatEq(dy, 0.0))
    scroll_buffer->Insert(
        dx, dy,
        state_buffer.Get(0)->timestamp - state_buffer.Get(1)->timestamp);
  return true;
}

void ScrollManager::UpdateScrollEventBuffer(
    GestureType gesture_type, ScrollEventBuffer* scroll_buffer) const {
  if (gesture_type != kGestureTypeScroll)
    scroll_buffer->Clear();
}

size_t ScrollManager::ScrollEventsForFlingCount(
    const ScrollEventBuffer& scroll_buffer) const {
  if (scroll_buffer.Size() <= 1)
    return scroll_buffer.Size();
  enum Direction { kNone, kUp, kDown, kLeft, kRight };
  size_t i = 0;
  Direction prev_direction = kNone;
  size_t fling_buffer_depth = static_cast<size_t>(fling_buffer_depth_.val_);
  for (; i < scroll_buffer.Size() && i < fling_buffer_depth; i++) {
    const ScrollEvent& event = scroll_buffer.Get(i);
    if (FloatEq(event.dx, 0.0) && FloatEq(event.dy, 0.0))
      break;
    Direction direction;
    if (fabsf(event.dx) > fabsf(event.dy))
      direction = event.dx > 0 ? kRight : kLeft;
    else
      direction = event.dy > 0 ? kDown : kUp;
    if (i > 0 && direction != prev_direction)
      break;
    prev_direction = direction;
  }
  return i;
}

void ScrollManager::RegressScrollVelocity(
    const ScrollEventBuffer& scroll_buffer, int count, ScrollEvent* out) const {
  struct RegressionSums {
    float tt_;  // Cumulative sum of t^2.
    float t_;   // Cumulative sum of t.
    float tx_;  // Cumulative sum of t * x.
    float ty_;  // Cumulative sum of t * y.
    float x_;   // Cumulative sum of x.
    float y_;   // Cumulative sum of y.
  };

  out->dt = 1;
  if (count <= 1) {
    out->dx = 0;
    out->dy = 0;
    return;
  }

  RegressionSums sums = {0, 0, 0, 0, 0, 0};

  float time = 0;
  float x_coord = 0;
  float y_coord = 0;

  for (int i = count - 1; i >= 0; --i) {
    const ScrollEvent& event = scroll_buffer.Get(i);

    time += event.dt;
    x_coord += event.dx;
    y_coord += event.dy;

    sums.tt_ += time * time;
    sums.t_ += time;
    sums.tx_ += time * x_coord;
    sums.ty_ += time * y_coord;
    sums.x_ += x_coord;
    sums.y_ += y_coord;
  }

  // Note the regression determinant only depends on the values of t, and should
  // never be zero so long as (1) count > 1, and (2) dt values are all non-zero.
  float det = count * sums.tt_ - sums.t_ * sums.t_;

  if (det) {
    float det_inv = 1.0 / det;

    out->dx = (count * sums.tx_ - sums.t_ * sums.x_) * det_inv;
    out->dy = (count * sums.ty_ - sums.t_ * sums.y_) * det_inv;
  } else {
    out->dx = 0;
    out->dy = 0;
  }
}

bool ScrollManager::SuppressStationaryFingerMovement(const FingerState& fs,
                                                     const FingerState& prev,
                                                     stime_t dt) {
  if (max_stationary_move_speed_.val_ <= 0.0 ||
      max_stationary_move_suppress_distance_.val_ <= 0.0)
    return false;
  float dist_sq = DistSq(fs, prev);
  // If speed exceeded, allow free movement and discard history
  if (dist_sq > dt * dt *
      max_stationary_move_speed_.val_ * max_stationary_move_speed_.val_) {
    stationary_move_distance_.erase(fs.tracking_id);
    return false;
  }

  float dist = sqrtf(dist_sq);
  if (dist_sq <= dt * dt *
      max_stationary_move_speed_hysteresis_.val_ *
      max_stationary_move_speed_hysteresis_.val_ &&
      !MapContainsKey(stationary_move_distance_, fs.tracking_id)) {
    // We assume that the first nearly-stationay event won't exceed the
    // distance threshold and return from here.
    stationary_move_distance_[fs.tracking_id] = dist;
    return true;
  }

  if (!MapContainsKey(stationary_move_distance_, fs.tracking_id)) {
    return false;
  }

  // Check if distance exceeded. If so, keep history and allow motion
  stationary_move_distance_[fs.tracking_id] += dist;
  return stationary_move_distance_[fs.tracking_id] <
      max_stationary_move_suppress_distance_.val_;
}

void ScrollManager::ComputeFling(const HardwareStateBuffer& state_buffer,
                                 const ScrollEventBuffer& scroll_buffer,
                                 Gesture* result) const {
  if (!did_generate_scroll_)
    return;
  ScrollEvent out = { 0.0, 0.0, 0.0 };
  ScrollEvent zero = { 0.0, 0.0, 0.0 };
  size_t count = 0;

  // Make sure fling buffer met the minimum average speed for a fling.
  float buf_dist_sq = 0.0;
  float buf_dt = 0.0;
  scroll_buffer.GetSpeedSq(fling_buffer_depth_.val_, &buf_dist_sq, &buf_dt);
  if (fling_buffer_min_avg_speed_.val_ * fling_buffer_min_avg_speed_.val_ *
      buf_dt * buf_dt > buf_dist_sq) {
    out = zero;
    goto done;
  }

  count = ScrollEventsForFlingCount(scroll_buffer);
  if (count > scroll_buffer.Size()) {
    Err("Too few events in scroll buffer");
    out = zero;
    goto done;
  }

  if (count < 2) {
    if (count == 0)
      out = zero;
    else if (count == 1)
      out = scroll_buffer.Get(0);
    goto done;
  }

  // If we get here, count == 3 && scroll_buffer.Size() >= 3
  RegressScrollVelocity(scroll_buffer, count, &out);

done:
  float vx = out.dt ? (out.dx / out.dt) : 0.0;
  float vy = out.dt ? (out.dy / out.dt) : 0.0;
  *result = Gesture(kGestureFling,
                    state_buffer.Get(1)->timestamp,
                    state_buffer.Get(0)->timestamp,
                    vx,
                    vy,
                    GESTURES_FLING_START);
}

FingerButtonClick::FingerButtonClick(const ImmediateInterpreter* interpreter)
    : interpreter_(interpreter),
      fingers_(),
      fingers_status_(),
      num_fingers_(0),
      num_recent_(0),
      num_cold_(0),
      num_hot_(0) {
}

bool FingerButtonClick::Update(const HardwareState& hwstate,
                               stime_t button_down_time) {
  const float kMoveDistSq = interpreter_->button_move_dist_.val_ *
                            interpreter_->button_move_dist_.val_;

  // Copy all fingers to an array, but leave out palms
  num_fingers_ = 0;
  for (int i = 0; i < hwstate.touch_cnt; ++i) {
    const FingerState& fs = hwstate.fingers[i];
    if (fs.flags & (GESTURES_FINGER_PALM | GESTURES_FINGER_POSSIBLE_PALM))
      continue;
    // we don't support more than 4 fingers
    if (num_fingers_ >= 4)
      return false;
    fingers_[num_fingers_++] = &fs;
  }

  // Single finger is trivial
  if (num_fingers_ <= 1)
    return false;

  // Sort fingers array by origin timestamp
  FingerOriginCompare comparator(interpreter_);
  std::sort(fingers_, fingers_ + num_fingers_, comparator);

  // The status describes if a finger is recent (touched down recently),
  // cold (touched down a while ago, but did not move) or hot (has moved).
  // However thumbs are always forced to be "cold".
  for (int i = 0; i < num_fingers_; ++i) {
    stime_t finger_age =
        button_down_time -
        interpreter_->finger_origin_timestamp(fingers_[i]->tracking_id);
    bool moving_finger =
        SetContainsValue(interpreter_->moving_, fingers_[i]->tracking_id) ||
        (interpreter_->DistanceTravelledSq(*fingers_[i], true) > kMoveDistSq);
    if (!SetContainsValue(interpreter_->pointing_, fingers_[i]->tracking_id))
      fingers_status_[i] = STATUS_COLD;
    else if (moving_finger)
      fingers_status_[i] = STATUS_HOT;
    else if (finger_age < interpreter_->right_click_second_finger_age_.val_)
      fingers_status_[i] = STATUS_RECENT;
    else
      fingers_status_[i] = STATUS_COLD;
  }

  num_recent_ = 0;
  for (int i = 0; i < num_fingers_; ++i)
    num_recent_ += (fingers_status_[i] == STATUS_RECENT);

  num_cold_ = 0;
  for (int i = 0; i < num_fingers_; ++i)
    num_cold_ += (fingers_status_[i] == STATUS_COLD);

  num_hot_ = num_fingers_ - num_recent_ - num_cold_;
  return true;
}

int FingerButtonClick::GetButtonTypeForTouchCount(int touch_count) const {
  if (touch_count == 2)
    return GESTURES_BUTTON_RIGHT;
  if (touch_count == 3 && interpreter_->three_finger_click_enable_.val_)
    return GESTURES_BUTTON_MIDDLE;
  return GESTURES_BUTTON_LEFT;
}

int FingerButtonClick::EvaluateTwoFingerButtonType() {
  // Only one finger hot -> moving -> left click
  if (num_hot_ == 1)
    return GESTURES_BUTTON_LEFT;

  float start_delta =
      fabs(interpreter_->finger_origin_timestamp(fingers_[0]->tracking_id) -
           interpreter_->finger_origin_timestamp(fingers_[1]->tracking_id));

  // check if fingers are too close for a right click
  const float kMin2fDistThreshSq =
      interpreter_->tapping_finger_min_separation_.val_ *
      interpreter_->tapping_finger_min_separation_.val_;
  float dist_sq = DistSq(*fingers_[0], *fingers_[1]);
  if (dist_sq < kMin2fDistThreshSq)
    return GESTURES_BUTTON_LEFT;

  // fingers touched down at approx the same time
  if (start_delta < interpreter_->right_click_start_time_diff_.val_) {
    // If two fingers are both very recent, it could either be a right-click
    // or the left-click of one click-and-drag gesture. Our heuristic is that
    // for real right-clicks, two finger's pressure should be roughly the same
    // and they tend not be vertically aligned.
    const FingerState* min_fs = NULL;
    const FingerState* fs = NULL;
    if (fingers_[0]->pressure < fingers_[1]->pressure)
      min_fs = fingers_[0], fs = fingers_[1];
    else
      min_fs = fingers_[1], fs = fingers_[0];
    float min_pressure = min_fs->pressure;
    // It takes higher pressure for the bottom finger to trigger the physical
    // click and people tend to place fingers more vertically so that they have
    // enough space to drag the content with ease.
    bool likely_click_drag =
        (fs->pressure >
             min_pressure +
                 interpreter_->click_drag_pressure_diff_thresh_.val_ &&
         fs->pressure >
             min_pressure *
                 interpreter_->click_drag_pressure_diff_factor_.val_ &&
         fs->position_y > min_fs->position_y);
    float xdist = fabsf(fs->position_x - min_fs->position_x);
    float ydist = fabsf(fs->position_y - min_fs->position_y);
    if (likely_click_drag &&
        ydist >= xdist * interpreter_->click_drag_min_slope_.val_)
      return GESTURES_BUTTON_LEFT;
    return GESTURES_BUTTON_RIGHT;
  }

  // 1 finger is cold and in the dampened zone? Probably a thumb!
  if (num_cold_ == 1 && interpreter_->FingerInDampenedZone(*fingers_[0]))
    return GESTURES_BUTTON_LEFT;

  // Close fingers -> same hand -> right click
  // Fingers apart -> second hand finger or thumb -> left click
  if (interpreter_->TwoFingersGesturing(*fingers_[0], *fingers_[1], true))
    return GESTURES_BUTTON_RIGHT;
  else
    return GESTURES_BUTTON_LEFT;
}

int FingerButtonClick::EvaluateThreeOrMoreFingerButtonType() {
  // Treat recent, ambiguous fingers as thumbs if they are in the dampened
  // zone.
  int num_dampened_recent = 0;
  for (int i = num_fingers_ - num_recent_; i < num_fingers_; ++i)
    num_dampened_recent += interpreter_->FingerInDampenedZone(*fingers_[i]);

  // Re-use the 2f button type logic in case that all recent fingers are
  // presumed thumbs because the recent fingers could be from thumb splits
  // due to the increased pressure when doing a physical click and should be
  // ignored.
  if ((num_fingers_ - num_recent_ == 2) &&
      (num_recent_ == num_dampened_recent))
    return EvaluateTwoFingerButtonType();

  // Only one finger hot with all others cold -> moving -> left click
  if (num_hot_ == 1 && num_cold_ == num_fingers_ - 1)
    return GESTURES_BUTTON_LEFT;

  // A single recent touch, or a single cold touch (with all others being hot)
  // could be a thumb or a second hand finger.
  if (num_recent_ == 1 || (num_cold_ == 1 && num_hot_ == num_fingers_ - 1)) {
    // The ambiguous finger is either the most recent one, or the only cold one.
    const FingerState* ambiguous_finger = fingers_[num_fingers_ - 1];
    if (num_recent_ != 1) {
      for (int i = 0; i < num_fingers_; ++i) {
        if (fingers_status_[i] == STATUS_COLD) {
          ambiguous_finger = fingers_[i];
          break;
        }
      }
    }
    // If it's in the dampened zone we will expect it to be a thumb.
    // Otherwise it's a second hand finger
    if (interpreter_->FingerInDampenedZone(*ambiguous_finger))
      return GetButtonTypeForTouchCount(num_fingers_ - 1);
    else
      return GESTURES_BUTTON_LEFT;
  }

  // If all fingers are recent we can be sure they are from the same hand.
  if (num_recent_ == num_fingers_) {
    // Only if all fingers are in the same zone, we can be sure that none
    // of them is a thumb.
    Log("EvaluateThreeOrMoreFingerButtonType: Dampened: %d",
        num_dampened_recent);
    if (num_dampened_recent == 0 || num_dampened_recent == num_recent_)
      return GetButtonTypeForTouchCount(num_recent_);
  }

  // To make a decision after this point we need to figure out if and how
  // many of the fingers are grouped together. We do so by finding the pair
  // of closest fingers, and then calculate where we expect the remaining
  // fingers to be found.
  // If they are not in the expected place, they will be called separate.
  Log("EvaluateThreeOrMoreFingerButtonType: Falling back to location based "
      "detection");
  return EvaluateButtonTypeUsingFigureLocation();
}

int FingerButtonClick::EvaluateButtonTypeUsingFigureLocation() {
  const float kMaxDistSq = interpreter_->button_max_dist_from_expected_.val_ *
                           interpreter_->button_max_dist_from_expected_.val_;

  // Find pair with the closest distance
  const FingerState* pair_a = NULL;
  const FingerState* pair_b = NULL;
  float pair_dist_sq = std::numeric_limits<float>::infinity();
  for (int i = 0; i < num_fingers_; ++i) {
    for (int j = 0; j < i; ++j) {
      float dist_sq = DistSq(*fingers_[i], *fingers_[j]);
      if (dist_sq < pair_dist_sq) {
        pair_a = fingers_[i];
        pair_b = fingers_[j];
        pair_dist_sq = dist_sq;
      }
    }
  }

  int num_separate = 0;
  const FingerState* last_separate = NULL;

  if (interpreter_->metrics_->CloseEnoughToGesture(Vector2(*pair_a),
                                                   Vector2(*pair_b))) {
    // Expect the remaining fingers to be next to the pair, all with the same
    // distance from each other.
    float dx = pair_b->position_x - pair_a->position_x;
    float dy = pair_b->position_y - pair_a->position_y;
    float expected1_x = pair_a->position_x + 2 * dx;
    float expected1_y = pair_a->position_y + 2 * dy;
    float expected2_x = pair_b->position_x - 2 * dx;
    float expected2_y = pair_b->position_y - 2 * dy;

    // Check if remaining fingers are close to the expected positions
    for (int i = 0; i < num_fingers_; ++i) {
      if (fingers_[i] == pair_a || fingers_[i] == pair_b)
        continue;
      float dist1_sq = DistSqXY(*fingers_[i], expected1_x, expected1_y);
      float dist2_sq = DistSqXY(*fingers_[i], expected2_x, expected2_y);
      if (dist1_sq > kMaxDistSq && dist2_sq > kMaxDistSq) {
        num_separate++;
        last_separate = fingers_[i];
      }
    }
  } else {
    // In case the pair is not close we have to fall back to using the
    // dampened zone
    Log("EvaluateButtonTypeUsingFigureLocation: Falling back to dampened zone "
        "separation");
    for (int i = 0; i < num_fingers_; ++i) {
      if (interpreter_->FingerInDampenedZone(*fingers_[i])) {
        num_separate++;
        last_separate = fingers_[i];
      }
    }
  }

  // All fingers next to each other
  if (num_separate == 0)
    return GetButtonTypeForTouchCount(num_fingers_);

  // The group with the last finger counts!
  // Exception: If the separates have only one finger and it's a thumb
  //            count the other group
  int num_pressing;
  if (fingers_[num_fingers_ - 1] == last_separate &&
      !(num_separate == 1 &&
        interpreter_->FingerInDampenedZone(*last_separate))) {
    num_pressing = num_separate;
  } else {
    num_pressing = num_fingers_ - num_separate;
  }
  Log("EvaluateButtonTypeUsingFigureLocation: Pressing: %d", num_pressing);
  return GetButtonTypeForTouchCount(num_pressing);
}

ImmediateInterpreter::ImmediateInterpreter(PropRegistry* prop_reg,
                                           Tracer* tracer)
    : Interpreter(NULL, tracer, false),
      button_type_(0),
      finger_button_click_(this),
      sent_button_down_(false),
      button_down_timeout_(0.0),
      started_moving_time_(-1.0),
      gs_changed_time_(-1.0),
      finger_leave_time_(0.0),
      moving_finger_id_(-1),
      tap_to_click_state_(kTtcIdle),
      tap_to_click_state_entered_(0.0),
      tap_record_(this),
      last_movement_timestamp_(0.0),
      last_swipe_timestamp_(0.0),
      swipe_is_vertical_(false),
      current_gesture_type_(kGestureTypeNull),
      state_buffer_(4),
      scroll_buffer_(20),
      pinch_guess_start_(-1.0),
      pinch_locked_(false),
      finger_seen_shortly_after_button_down_(false),
      scroll_manager_(prop_reg),
      tap_enable_(prop_reg, "Tap Enable", true),
      tap_paused_(prop_reg, "Tap Paused", false),
      tap_timeout_(prop_reg, "Tap Timeout", 0.2),
      inter_tap_timeout_(prop_reg, "Inter-Tap Timeout", 0.15),
      tap_drag_delay_(prop_reg, "Tap Drag Delay", 0.05),
      tap_drag_timeout_(prop_reg, "Tap Drag Timeout", 0.3),
      tap_drag_enable_(prop_reg, "Tap Drag Enable", 0),
      drag_lock_enable_(prop_reg, "Tap Drag Lock Enable", 0),
      tap_drag_stationary_time_(prop_reg, "Tap Drag Stationary Time", 0),
      tap_move_dist_(prop_reg, "Tap Move Distance", 2.0),
      tap_min_pressure_(prop_reg, "Tap Minimum Pressure", 25.0),
      tap_max_movement_(prop_reg, "Tap Maximum Movement", 0.0001),
      tap_max_finger_age_(prop_reg, "Tap Maximum Finger Age", 1.2),
      three_finger_click_enable_(prop_reg, "Three Finger Click Enable", 1),
      zero_finger_click_enable_(prop_reg, "Zero Finger Click Enable", 1),
      t5r2_three_finger_click_enable_(prop_reg,
                                      "T5R2 Three Finger Click Enable",
                                      0),
      change_move_distance_(prop_reg, "Change Min Move Distance", 3.0),
      change_timeout_(prop_reg, "Change Timeout", 0.04),
      evaluation_timeout_(prop_reg, "Evaluation Timeout", 0.2),
      damp_scroll_min_movement_factor_(prop_reg,
                                       "Damp Scroll Min Move Factor",
                                       0.2),
      two_finger_pressure_diff_thresh_(prop_reg,
                                       "Two Finger Pressure Diff Thresh",
                                       32.0),
      two_finger_pressure_diff_factor_(prop_reg,
                                       "Two Finger Pressure Diff Factor",
                                       1.65),
      click_drag_pressure_diff_thresh_(prop_reg,
                                       "Click Drag Pressure Diff Thresh",
                                       10.0),
      click_drag_pressure_diff_factor_(prop_reg,
                                       "Click Drag Pressure Diff Factor",
                                       1.20),
      click_drag_min_slope_(prop_reg, "Click Drag Min Slope", 2.22),
      thumb_movement_factor_(prop_reg, "Thumb Movement Factor", 0.5),
      thumb_speed_factor_(prop_reg, "Thumb Speed Factor", 0.5),
      thumb_eval_timeout_(prop_reg, "Thumb Evaluation Timeout", 0.06),
      thumb_click_prevention_timeout_(prop_reg,
                                      "Thumb Click Prevention Timeout", 0.2),
      two_finger_scroll_distance_thresh_(prop_reg,
                                         "Two Finger Scroll Distance Thresh",
                                         2.0),
      three_finger_close_distance_thresh_(prop_reg,
                                          "Three Finger Close Distance Thresh",
                                          50.0),
      three_finger_swipe_distance_thresh_(prop_reg,
                                          "Three Finger Swipe Distance Thresh",
                                          1.0),
      three_finger_swipe_enable_(prop_reg, "Three Finger Swipe EnableX", 1),
      scroll_stationary_finger_max_distance_(
          prop_reg, "Scroll Stationary Finger Max Distance", 1.0),
      bottom_zone_size_(prop_reg, "Bottom Zone Size", 10.0),
      button_evaluation_timeout_(prop_reg, "Button Evaluation Timeout", 0.05),
      button_finger_timeout_(prop_reg, "Button Finger Timeout", 0.03),
      button_move_dist_(prop_reg, "Button Move Distance", 10.0),
      button_max_dist_from_expected_(prop_reg,
                                     "Button Max Distance From Expected", 20.0),
      button_right_click_zone_enable_(prop_reg,
                                      "Button Right Click Zone Enable", 0),
      button_right_click_zone_size_(prop_reg,
                                    "Button Right Click Zone Size", 20.0),
      keyboard_touched_timeval_high_(prop_reg, "Keyboard Touched Timeval High",
                                     0),
      keyboard_touched_timeval_low_(prop_reg, "Keyboard Touched Timeval Low",
                                    0, this),
      keyboard_touched_(0.0),
      keyboard_palm_prevent_timeout_(prop_reg, "Keyboard Palm Prevent Timeout",
                                     0.5),
      motion_tap_prevent_timeout_(prop_reg, "Motion Tap Prevent Timeout",
                                  0.05),
      tapping_finger_min_separation_(prop_reg, "Tap Min Separation", 10.0),
      no_pinch_guess_ratio_(prop_reg, "No-Pinch Guess Ratio", 0.9),
      no_pinch_certain_ratio_(prop_reg, "No-Pinch Certain Ratio", 2.0),
      pinch_noise_level_(prop_reg, "Pinch Noise Level", 1.0),
      pinch_guess_min_movement_(prop_reg, "Pinch Guess Minimal Movement", 4.0),
      pinch_certain_min_movement_(prop_reg,
                                  "Pinch Certain Minimal Movement", 8.0),
      pinch_enable_(prop_reg, "Pinch Enable", 0),
      right_click_start_time_diff_(prop_reg,
                                   "Right Click Start Time Diff Thresh",
                                   0.1),
      right_click_second_finger_age_(prop_reg,
                                     "Right Click Second Finger Age Thresh",
                                     0.5),
      quick_acceleration_factor_(prop_reg, "Quick Acceleration Factor", 0.0) {
  InitName();
  requires_metrics_ = true;
}

void ImmediateInterpreter::SyncInterpretImpl(HardwareState* hwstate,
                                             stime_t* timeout) {
  if (!state_buffer_.Get(0)->fingers) {
    Err("Must call SetHardwareProperties() before Push().");
    return;
  }

  state_buffer_.PushState(*hwstate);

  FillOriginInfo(*hwstate);
  result_.type = kGestureTypeNull;
  const bool same_fingers = state_buffer_.Get(1)->SameFingersAs(*hwstate) &&
      (hwstate->buttons_down == state_buffer_.Get(1)->buttons_down);
  if (!same_fingers) {
    // Fingers changed, do nothing this time
    ResetSameFingersState(*hwstate);
    FillStartPositions(*hwstate);
    UpdatePinchState(*hwstate, true);
    moving_finger_id_ = -1;
  }

  if (hwstate->finger_cnt < state_buffer_.Get(1)->finger_cnt)
    finger_leave_time_ = hwstate->timestamp;

  UpdatePointingFingers(*hwstate);
  UpdateThumbState(*hwstate);
  FingerMap newly_moving_fingers = UpdateMovingFingers(*hwstate);
  UpdateNonGsFingers(*hwstate);
  FingerMap gs_fingers =
      SetSubtract(GetGesturingFingers(*hwstate), non_gs_fingers_);
  if (gs_fingers != prev_gs_fingers_)
    gs_changed_time_ = hwstate->timestamp;
  UpdateStartedMovingTime(hwstate->timestamp, gs_fingers, newly_moving_fingers);

  UpdateButtons(*hwstate, timeout);
  UpdateTapGesture(hwstate,
                   gs_fingers,
                   same_fingers,
                   hwstate->timestamp,
                   timeout);

  FingerMap active_gs_fingers;
  UpdateCurrentGestureType(*hwstate, gs_fingers, &active_gs_fingers);
  non_gs_fingers_ = SetSubtract(gs_fingers, active_gs_fingers);
  if (result_.type == kGestureTypeNull)
    FillResultGesture(*hwstate, active_gs_fingers);

  // Prevent moves while in a tap
  if ((tap_to_click_state_ == kTtcFirstTapBegan ||
       tap_to_click_state_ == kTtcSubsequentTapBegan) &&
      result_.type == kGestureTypeMove)
    result_.type = kGestureTypeNull;

  prev_active_gs_fingers_ = active_gs_fingers;
  prev_gs_fingers_ = gs_fingers;
  prev_result_ = result_;
  prev_gesture_type_ = current_gesture_type_;
  if (result_.type != kGestureTypeNull)
    ProduceGesture(result_);
}

void ImmediateInterpreter::HandleTimerImpl(stime_t now, stime_t* timeout) {
  result_.type = kGestureTypeNull;
  // Tap-to-click always aborts when real button(s) are being used, so we
  // don't need to worry about conflicts with these two types of callback.
  UpdateButtonsTimeout(now);
  UpdateTapGesture(NULL,
                   FingerMap(),
                   false,
                   now,
                   timeout);
  if (result_.type != kGestureTypeNull)
    ProduceGesture(result_);
}

void ImmediateInterpreter::FillOriginInfo(
    const HardwareState& hwstate) {
  RemoveMissingIdsFromMap(&origin_timestamps_, hwstate);
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    const FingerState& fs = hwstate.fingers[i];
    if (MapContainsKey(origin_timestamps_, fs.tracking_id))
      continue;
    origin_timestamps_[fs.tracking_id] = hwstate.timestamp;
  }
}

void ImmediateInterpreter::ResetSameFingersState(const HardwareState& hwstate) {
  pointing_.clear();
  fingers_.clear();
  start_positions_.clear();
  scroll_manager_.ResetSameFingerState();
  RemoveMissingIdsFromSet(&moving_, hwstate);
  changed_time_ = hwstate.timestamp;
}

void ImmediateInterpreter::UpdatePointingFingers(const HardwareState& hwstate) {
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    if (hwstate.fingers[i].flags & GESTURES_FINGER_PALM)
      pointing_.erase(hwstate.fingers[i].tracking_id);
    else
      pointing_.insert(hwstate.fingers[i].tracking_id);
  }
  fingers_ = pointing_;
}

float ImmediateInterpreter::DistanceTravelledSq(const FingerState& fs,
                                                bool origin,
                                                bool permit_warp) const {
  Point delta = FingerTraveledVector(fs, origin, permit_warp);
  return delta.x_ * delta.x_ + delta.y_ * delta.y_;
}

ImmediateInterpreter::Point ImmediateInterpreter::FingerTraveledVector(
    const FingerState& fs, bool origin, bool permit_warp) const {
  const map<short, Point, kMaxFingers>* positions;
  if (origin)
    positions = &origin_positions_;
  else
    positions = &start_positions_;

  if (!MapContainsKey(*positions, fs.tracking_id))
    return Point(0.0f, 0.0f);

  const Point& start = (*positions)[fs.tracking_id];
  float dx = fs.position_x - start.x_;
  float dy = fs.position_y - start.y_;
  bool suppress_move =
      (!permit_warp || (fs.flags & GESTURES_FINGER_WARP_TELEPORTATION));
  if ((fs.flags & GESTURES_FINGER_WARP_X) && suppress_move)
    dx = 0;
  if ((fs.flags & GESTURES_FINGER_WARP_Y) && suppress_move)
    dy = 0;
  return Point(dx, dy);
}

float ImmediateInterpreter::TwoFingerDistanceSq(
    const HardwareState& hwstate) const {
  if (fingers_.size() == 2) {
    const FingerState* finger_a = hwstate.GetFingerState(*fingers_.begin());
    const FingerState* finger_b = hwstate.GetFingerState(*(fingers_.begin()+1));
    if (finger_a == NULL || finger_b == NULL) {
      Err("Finger unexpectedly NULL");
      return -1;
    }
    return DistSq(*finger_a, *finger_b);
  } else {
    return -1;
  }
}

// Updates thumb_ below.
void ImmediateInterpreter::UpdateThumbState(const HardwareState& hwstate) {
  // Remove old ids from thumb_
  RemoveMissingIdsFromMap(&thumb_, hwstate);
  RemoveMissingIdsFromMap(&thumb_eval_timer_, hwstate);
  float min_pressure = INFINITY;
  const FingerState* min_fs = NULL;
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    const FingerState& fs = hwstate.fingers[i];
    if (fs.flags & GESTURES_FINGER_PALM)
      continue;
    if (fs.pressure < min_pressure) {
      min_pressure = fs.pressure;
      min_fs = &fs;
    }
  }
  if (!min_fs) {
    // Only palms on the touchpad
    return;
  }
  // We respect warp flags only if we really have little information of the
  // finger positions and not just because we want to suppress unintentional
  // cursor moves. See the definition of GESTURES_FINGER_WARP_TELEPORTATION
  // for more detail.
  bool min_warp_move = (min_fs->flags & GESTURES_FINGER_WARP_TELEPORTATION) &&
                       ((min_fs->flags & GESTURES_FINGER_WARP_X_MOVE) ||
                        (min_fs->flags & GESTURES_FINGER_WARP_Y_MOVE));
  float min_dist_sq = DistanceTravelledSq(*min_fs, true, true);
  float min_dt = hwstate.timestamp -
      origin_timestamps_[min_fs->tracking_id];
  float thumb_dist_sq_thresh = min_dist_sq *
      thumb_movement_factor_.val_ * thumb_movement_factor_.val_;
  float thumb_speed_sq_thresh = min_dist_sq *
      thumb_speed_factor_.val_ * thumb_speed_factor_.val_;
  // Make all large-pressure, less moving contacts located below the
  // min-pressure contact as thumbs.
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    const FingerState& fs = hwstate.fingers[i];
    if (fs.flags & GESTURES_FINGER_PALM)
      continue;
    float dist_sq = DistanceTravelledSq(fs, true, true);
    float dt = hwstate.timestamp - origin_timestamps_[fs.tracking_id];
    bool closer_to_origin = dist_sq <= thumb_dist_sq_thresh;
    bool slower_moved = (dist_sq * min_dt &&
                         dist_sq * min_dt * min_dt <
                         thumb_speed_sq_thresh * dt * dt);
    bool relatively_motionless = closer_to_origin || slower_moved;
    bool likely_thumb =
        (fs.pressure > min_pressure + two_finger_pressure_diff_thresh_.val_ &&
         fs.pressure > min_pressure * two_finger_pressure_diff_factor_.val_ &&
         fs.position_y > min_fs->position_y);
    // We sometimes can't decide the thumb state if some fingers are undergoing
    // warp moves as the decision could be off (DistanceTravelledSq may
    // under-estimate the real distance). The cases that we need to re-evaluate
    // the thumb in the next frame are:
    // 1. Both fingers warp.
    // 2. Min-pressure finger warps and relatively_motionless is false.
    // 3. Thumb warps and relatively_motionless is true.
    bool warp_move = (fs.flags & GESTURES_FINGER_WARP_TELEPORTATION) &&
                     ((fs.flags & GESTURES_FINGER_WARP_X_MOVE) ||
                      (fs.flags & GESTURES_FINGER_WARP_Y_MOVE));
    if (likely_thumb &&
        ((warp_move && min_warp_move) ||
         (!warp_move && min_warp_move && !relatively_motionless) ||
         (warp_move && !min_warp_move && relatively_motionless))) {
      continue;
    }
    likely_thumb &= relatively_motionless;

    if (MapContainsKey(thumb_, fs.tracking_id)) {
      // Beyond the evaluation period. Stick to being thumbs.
      if (thumb_eval_timer_[fs.tracking_id] <= 0.0)
        continue;

      // Finger is still under evaluation.
      if (likely_thumb) {
        // Decrease the timer as the finger is thumb-like in the previous
        // frame.
        const FingerState* prev =
            state_buffer_.Get(1)->GetFingerState(fs.tracking_id);
        if (!prev)
          continue;
        thumb_eval_timer_[fs.tracking_id] -=
            hwstate.timestamp - state_buffer_.Get(1)->timestamp;
      } else {
        // The finger wasn't thumb-like in the frame. Remove it from the thumb
        // list.
        thumb_.erase(fs.tracking_id);
        thumb_eval_timer_.erase(fs.tracking_id);
      }
    } else if (likely_thumb) {
      // Finger is thumb-like, so we add it to the list.
      thumb_[fs.tracking_id] = hwstate.timestamp;
      thumb_eval_timer_[fs.tracking_id] = thumb_eval_timeout_.val_;
    }
  }
  for (map<short, stime_t, kMaxFingers>::const_iterator it = thumb_.begin();
       it != thumb_.end(); ++it)
    pointing_.erase((*it).first);
}

void ImmediateInterpreter::UpdateNonGsFingers(const HardwareState& hwstate) {
  RemoveMissingIdsFromSet(&non_gs_fingers_, hwstate);
  // moving fingers may be gesturing, so take them out from the set.
  non_gs_fingers_ = SetSubtract(non_gs_fingers_, moving_);
}

bool ImmediateInterpreter::KeyboardRecentlyUsed(stime_t now) const {
  // For tests, values of 0 mean keyboard not used recently.
  if (keyboard_touched_ == 0.0)
    return false;
  // Sanity check. If keyboard_touched_ is more than 10 seconds away from now,
  // ignore it.
  if (fabs(now - keyboard_touched_) > 10)
    return false;

  return keyboard_touched_ + keyboard_palm_prevent_timeout_.val_ > now;
}

namespace {
struct GetGesturingFingersCompare {
  // Returns true if finger_a is strictly closer to keyboard than finger_b
  bool operator()(const FingerState* finger_a, const FingerState* finger_b) {
    return finger_a->position_y < finger_b->position_y;
  }
};
}  // namespace {}

FingerMap ImmediateInterpreter::GetGesturingFingers(
    const HardwareState& hwstate) const {
  // We support up to kMaxGesturingFingers finger gestures
  if (pointing_.size() <= kMaxGesturingFingers)
    return pointing_;

  const FingerState* fs[hwstate.finger_cnt];
  for (size_t i = 0; i < hwstate.finger_cnt; ++i)
    fs[i] = &hwstate.fingers[i];

  // Pull the kMaxSize FingerStates w/ the lowest position_y to the
  // front of fs[].
  GetGesturingFingersCompare compare;
  FingerMap ret;
  size_t sorted_cnt;
  if (hwstate.finger_cnt > kMaxGesturingFingers) {
    std::partial_sort(fs, fs + kMaxGesturingFingers, fs + hwstate.finger_cnt,
                      compare);
    sorted_cnt = kMaxGesturingFingers;
  } else {
    std::sort(fs, fs + hwstate.finger_cnt, compare);
    sorted_cnt = hwstate.finger_cnt;
  }
  for (size_t i = 0; i < sorted_cnt; i++)
    ret.insert(fs[i]->tracking_id);
  return ret;
}

void ImmediateInterpreter::UpdateCurrentGestureType(
    const HardwareState& hwstate,
    const FingerMap& gs_fingers,
    FingerMap* active_gs_fingers) {
  *active_gs_fingers = gs_fingers;

  size_t num_gesturing = gs_fingers.size();

  // Physical button or tap overrides current gesture state
  if (sent_button_down_ || tap_to_click_state_ == kTtcDrag) {
    current_gesture_type_ = kGestureTypeMove;
    return;
  }

  // current gesture state machine
  switch (current_gesture_type_) {
    case kGestureTypeContactInitiated:
    case kGestureTypeButtonsChange:
      break;

    case kGestureTypeScroll:
    case kGestureTypeSwipe:
      // If a gesturing finger just left, do fling/lift
      if (AnyGesturingFingerLeft(*state_buffer_.Get(0),
                                 prev_gs_fingers_)) {
        current_gesture_type_ =
            current_gesture_type_ == kGestureTypeScroll ?
            kGestureTypeFling : kGestureTypeSwipeLift;
        return;
      }
      // fallthrough
    case kGestureTypeSwipeLift:
    case kGestureTypeFling:
    case kGestureTypeMove:
    case kGestureTypeNull:
      // When a finger leaves, we hold the gesture processing for
      // change_timeout_ time.
      if (hwstate.timestamp < finger_leave_time_ + change_timeout_.val_) {
        current_gesture_type_ = kGestureTypeNull;
        return;
      }

      // Scrolling detection for T5R2 devices
      if ((hwprops_->supports_t5r2 || hwprops_->support_semi_mt) &&
          (hwstate.touch_cnt > 2)) {
        current_gesture_type_ = kGestureTypeScroll;
        return;
      }

      // Finger gesture decision process
      if (num_gesturing == 0) {
        current_gesture_type_ = kGestureTypeNull;
      } else if (num_gesturing == 1) {
        const FingerState* finger =
            hwstate.GetFingerState(*gs_fingers.begin());
        if (PalmIsArrivingOrDeparting(*finger))
          current_gesture_type_ = kGestureTypeNull;
        else
          current_gesture_type_ = kGestureTypeMove;
      } else {
        if (changed_time_ > started_moving_time_ ||
            hwstate.timestamp - max(started_moving_time_, gs_changed_time_) <
            evaluation_timeout_.val_ ||
            current_gesture_type_ == kGestureTypeNull) {
          // Try to recognize gestures, starting from many-finger gestures
          // first. We choose this order b/c 3-finger gestures are very strict
          // in their interpretation.
          vector<short, kMaxGesturingFingers> sorted_ids;
          SortFingersByProximity(gs_fingers, hwstate, &sorted_ids);
          for (; sorted_ids.size() >= 2;
               sorted_ids.erase(sorted_ids.end() - 1)) {
            if (sorted_ids.size() == 2) {
              GestureType new_gs_type = kGestureTypeNull;
              const FingerState* fingers[] = {
                hwstate.GetFingerState(*sorted_ids.begin()),
                hwstate.GetFingerState(*(sorted_ids.begin() + 1))
              };
              if (!fingers[0] || !fingers[1]) {
                Err("Unable to find gesturing fingers!");
                return;
              }
              // See if two pointers are close together
              bool potential_two_finger_gesture =
                  TwoFingersGesturing(*fingers[0], *fingers[1], false);
              if (!potential_two_finger_gesture) {
                new_gs_type = kGestureTypeMove;
              } else {
                new_gs_type =
                    GetTwoFingerGestureType(*fingers[0], *fingers[1]);
                // Two fingers that don't end up causing scroll may be
                // ambiguous. Only move if they've been down long enough.
                if (new_gs_type == kGestureTypeMove &&
                    hwstate.timestamp -
                        max(origin_timestamps_[fingers[0]->tracking_id],
                            origin_timestamps_[fingers[1]->tracking_id]) <
                    evaluation_timeout_.val_)
                  new_gs_type = kGestureTypeNull;
              }
              if (new_gs_type != kGestureTypeMove ||
                  gs_fingers.size() == 2) {
                // We only allow this path to set a move gesture if there
                // are two fingers gesturing
                current_gesture_type_ = new_gs_type;
              }
            } else if (sorted_ids.size() == 3) {
              const FingerState* fingers[] = {
                hwstate.GetFingerState(*sorted_ids.begin()),
                hwstate.GetFingerState(*(sorted_ids.begin() + 1)),
                hwstate.GetFingerState(*(sorted_ids.begin() + 2))
              };
              if (!fingers[0] || !fingers[1] || !fingers[2]) {
                Err("Unable to find gesturing fingers!");
                return;
              }
              current_gesture_type_ = GetThreeFingerGestureType(fingers);
              if (current_gesture_type_ == kGestureTypeSwipe)
                last_swipe_timestamp_ = hwstate.timestamp;
            } else {
              Log("TODO(adlr): support > 3 finger gestures.");
            }
            if (current_gesture_type_ != kGestureTypeNull) {
              active_gs_fingers->clear();
              for (vector<short, kMaxGesturingFingers>::const_iterator it =
                   sorted_ids.begin(), e = sorted_ids.end(); it != e; ++it)
                active_gs_fingers->insert(*it);
              break;
            }
          }
        }
      }

      if ((current_gesture_type_ == kGestureTypeMove ||
           current_gesture_type_ == kGestureTypeNull) &&
          (pinch_enable_.val_ && !hwprops_->support_semi_mt)) {
        bool do_pinch = UpdatePinchState(hwstate, false);
        if(do_pinch) {
          current_gesture_type_ = kGestureTypePinch;
        }
      }
      break;

    case kGestureTypePinch:
      if (fingers_.size() == 2) {
        return;
      } else {
        current_gesture_type_ = kGestureTypeNull;
      }
      break;

    case kGestureTypeMetrics:
      // One shouldn't reach here
      Err("Metrics gestures reached ImmediateInterpreter");
      break;
  }
  return;
}

namespace {
// Can't use tuple<float, short, short> b/c we want to make a variable
// sized array of them on the stack
struct DistSqElt {
  float dist_sq;
  short tracking_id[2];
};

struct DistSqCompare {
  // Returns true if finger_a is strictly closer to keyboard than finger_b
  bool operator()(const DistSqElt& finger_a, const DistSqElt& finger_b) {
    return finger_a.dist_sq < finger_b.dist_sq;
  }
};

}  // namespace {}

void ImmediateInterpreter::SortFingersByProximity(
    const FingerMap& finger_ids,
    const HardwareState& hwstate,
    vector<short, kMaxGesturingFingers>* out_sorted_ids) {
  if (finger_ids.size() <= 2) {
    for (short finger_id : finger_ids)
      out_sorted_ids->push_back(finger_id);
    return;
  }
  // To do the sort, we sort all inter-point distances^2, then scan through
  // that until we have enough points
  size_t dist_sq_capacity =
      (finger_ids.size() * (finger_ids.size() - 1)) / 2;
  DistSqElt dist_sq[dist_sq_capacity];
  size_t dist_sq_len = 0;
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    const FingerState& fs1 = hwstate.fingers[i];
    if (!SetContainsValue(finger_ids, fs1.tracking_id))
      continue;
    for (size_t j = i + 1; j < hwstate.finger_cnt; j++) {
      const FingerState& fs2 = hwstate.fingers[j];
      if (!SetContainsValue(finger_ids, fs2.tracking_id))
        continue;
      DistSqElt elt = {
        DistSq(fs1, fs2),
        { fs1.tracking_id, fs2.tracking_id }
      };
      if (dist_sq_len >= dist_sq_capacity) {
        Err("%s: Array overrun", __func__);
        break;
      }
      dist_sq[dist_sq_len++] = elt;
    }
  }

  DistSqCompare distSqCompare;
  std::sort(dist_sq, dist_sq + dist_sq_len, distSqCompare);

  if (out_sorted_ids == NULL) {
    Err("out_sorted_ids became NULL");
    return;
  }
  for (size_t i = 0; i < dist_sq_len; i++) {
    short id1 = dist_sq[i].tracking_id[0];
    short id2 = dist_sq[i].tracking_id[1];
    bool contains1 = out_sorted_ids->find(id1) != out_sorted_ids->end();
    bool contains2 = out_sorted_ids->find(id2) != out_sorted_ids->end();
    if (contains1 == contains2 && !out_sorted_ids->empty()) {
      // Assuming we have some ids in the out vector, then either we have both
      // of these new ids, we have neither. Either way, we can't use this edge.
      continue;
    }
    if (!contains1)
      out_sorted_ids->push_back(id1);
    if (!contains2)
      out_sorted_ids->push_back(id2);
    if (out_sorted_ids->size() == finger_ids.size())
      break;  // We've got all the IDs
  }
}


bool ImmediateInterpreter::UpdatePinchState(
    const HardwareState& hwstate, bool reset) {

  // perform reset to "don't know" state
  if (reset) {
    pinch_guess_start_ = -1.0f;
    pinch_locked_ = false;
    two_finger_start_distance_ = -1.0f;
    return false;
  }

  // once locked stay locked until reset.
  if (pinch_locked_) {
    return false;
  }

  // check if we have two valid fingers
  if (fingers_.size() != 2) {
    return false;
  }
  const FingerState* finger1 = hwstate.GetFingerState(*fingers_.begin());
  const FingerState* finger2 = hwstate.GetFingerState(*(fingers_.begin()+1));
  if (finger1 == NULL || finger2 == NULL) {
    Err("Finger unexpectedly NULL");
    return false;
  }

  // assign the bottom finger to finger2
  if (finger1->position_y > finger2->position_y) {
    std::swap(finger1, finger2);
  }

  // Calculate start distance between fingers and cache value
  if (two_finger_start_distance_ < 0) {
    two_finger_start_distance_ = sqrtf(TwoFingerDistanceSq(hwstate));
  }

  // Check if the two fingers have start positions
  if (!MapContainsKey(start_positions_, finger1->tracking_id) ||
      !MapContainsKey(start_positions_, finger2->tracking_id)) {
    return false;
  }

  // Pinch gesture detection
  //
  // The pinch gesture detection will try to make a guess about whether a pinch
  // or not-a-pinch is performed. If the guess stays valid for a specific time
  // (slow but consistent movement) or we get a certain decision (fast
  // gesturing) the decision is locked until the state is reset.
  // * A high ratio of the traveled distances between fingers indicates
  //   that a pinch is NOT performed.
  // * Strong movement of both fingers in opposite directions indicates
  //   that a pinch IS performed.

  Point delta1 = FingerTraveledVector(*finger1, true);
  Point delta2 = FingerTraveledVector(*finger2, true);

  // dot product. dot < 0 if fingers move away from each other.
  float dot  = delta1.x_ * delta2.x_ + delta1.y_ * delta2.y_;
  // squared distances both finger have been traveled.
  float d1sq = delta1.x_ * delta1.x_ + delta1.y_ * delta1.y_;
  float d2sq = delta2.x_ * delta2.x_ + delta2.y_ * delta2.y_;

  // true if movement is not strong enough to be distinguished from noise.
  bool movement_below_noise = (d1sq + d2sq < 2.0*pinch_noise_level_.val_);

  // guesses if a pinch is being performed or not.
  double guess_min_mov = pinch_guess_min_movement_.val_;
  guess_min_mov *= guess_min_mov;
  bool no_pinch_guess = (d1sq  > guess_min_mov) ^ (d2sq > guess_min_mov) ||
                        dot > 0;
  bool pinch_guess = d1sq > guess_min_mov && d2sq > guess_min_mov && dot < 0;

  // Thumb is in dampened zone: Only allow inward pinch
  if (FingerInDampenedZone(*finger2)) {
    no_pinch_guess |= (delta2.y_ > 0);
    pinch_guess &= (delta2.y_ < 0);
  }

  // do state transitions and final decision
  if (pinch_guess_start_ < 0) {
    // "Don't Know"-state

    // Determine guess.
    if (!movement_below_noise) {
      if (no_pinch_guess && !pinch_guess) {
        pinch_guess_ = false;
        pinch_guess_start_ = hwstate.timestamp;
      }
      if (pinch_guess && !no_pinch_guess) {
        pinch_guess_ = true;
        pinch_guess_start_ = hwstate.timestamp;
      }
    }
  }
  if (pinch_guess_start_ >= 0) {
    // "Guessed"-state

    // suppress cursor movement when we guess a pinch gesture
    if (pinch_guess_) {
      for (size_t i = 0; i < hwstate.finger_cnt; ++i) {
        FingerState* finger_state = &hwstate.fingers[i];
        finger_state->flags |= GESTURES_FINGER_WARP_X;
        finger_state->flags |= GESTURES_FINGER_WARP_Y;
      }
    }

    // Go back to "Don't Know"-state if guess is no longer valid
    if (pinch_guess_ != pinch_guess ||
        pinch_guess_ == no_pinch_guess ||
        movement_below_noise) {
      pinch_guess_start_ = -1.0f;
      return false;
    }

    // certain decisions if pinch is being performed or not
    double cert_min_mov = pinch_certain_min_movement_.val_;
    cert_min_mov *= cert_min_mov;
    bool no_pinch_certain = false;
    bool pinch_certain = d1sq > cert_min_mov && d2sq > cert_min_mov && dot < 0;

    // guessed for long enough or certain decision was made: lock
    if (hwstate.timestamp - pinch_guess_start_ > 0.1 ||
        (pinch_certain && pinch_guess_) ||
        (no_pinch_certain && !pinch_guess_)) {
      pinch_locked_ = true;
      return pinch_guess_;
    }
  }

  return false;
}

bool ImmediateInterpreter::PalmIsArrivingOrDeparting(
    const FingerState& finger) const {
  if (((finger.flags & GESTURES_FINGER_POSSIBLE_PALM) ||
       (finger.flags & GESTURES_FINGER_PALM)) &&
      ((finger.flags & GESTURES_FINGER_TREND_INC_TOUCH_MAJOR) ||
       (finger.flags & GESTURES_FINGER_TREND_DEC_TOUCH_MAJOR)) &&
      ((finger.flags & GESTURES_FINGER_TREND_INC_PRESSURE) ||
       (finger.flags & GESTURES_FINGER_TREND_DEC_PRESSURE)))
    return true;
  return false;
}

bool ImmediateInterpreter::IsTooCloseToThumb(const FingerState& finger) const {
  const float kMin2fDistThreshSq = tapping_finger_min_separation_.val_ *
      tapping_finger_min_separation_.val_;
  for (map<short, stime_t, kMaxFingers>::const_iterator it = thumb_.begin();
       it != thumb_.end(); ++it) {
    const FingerState* thumb = state_buffer_.Get(0)->GetFingerState(it->first);
    float xdist = fabsf(finger.position_x - thumb->position_x);
    float ydist = fabsf(finger.position_y - thumb->position_y);
    if (xdist * xdist + ydist * ydist < kMin2fDistThreshSq)
      return true;
  }
  return false;
}

bool ImmediateInterpreter::TwoFingersGesturing(
    const FingerState& finger1,
    const FingerState& finger2,
    bool check_button_type) const {
  // Make sure distance between fingers isn't too great
  if (!metrics_->CloseEnoughToGesture(Vector2(finger1), Vector2(finger2)))
    return false;

  // Next, if two fingers are moving a lot, they are gesturing together.
  if (started_moving_time_ > changed_time_) {
    // Fingers are moving
    float dist1_sq = DistanceTravelledSq(finger1, false);
    float dist2_sq = DistanceTravelledSq(finger2, false);
    if (thumb_movement_factor_.val_ * thumb_movement_factor_.val_ *
        max(dist1_sq, dist2_sq) < min(dist1_sq, dist2_sq)) {
      return true;
    }
  }

  // Make sure the pressure difference isn't too great for vertically
  // aligned contacts
  float pdiff = fabsf(finger1.pressure - finger2.pressure);
  float xdist = fabsf(finger1.position_x - finger2.position_x);
  float ydist = fabsf(finger1.position_y - finger2.position_y);
  if (pdiff > two_finger_pressure_diff_thresh_.val_ && ydist > xdist &&
      ((finger1.pressure > finger2.pressure) ==
       (finger1.position_y > finger2.position_y)))
    return false;

  const float kMin2fDistThreshSq = tapping_finger_min_separation_.val_ *
      tapping_finger_min_separation_.val_;
  float dist_sq = xdist * xdist + ydist * ydist;
  // Make sure distance between fingers isn't too small
  if ((dist_sq < kMin2fDistThreshSq) &&
      !(finger1.flags & GESTURES_FINGER_MERGE))
    return false;

  // If both fingers have a tendency of moving at the same direction, they
  // are gesturing together. This check is disabled if we are using the
  // function to distinguish left/right clicks.
  if (!check_button_type) {
    unsigned and_flags = finger1.flags & finger2.flags;
    if ((and_flags & GESTURES_FINGER_TREND_INC_X) ||
        (and_flags & GESTURES_FINGER_TREND_DEC_X) ||
        (and_flags & GESTURES_FINGER_TREND_INC_Y) ||
        (and_flags & GESTURES_FINGER_TREND_DEC_Y))
      return true;
  }

  // Next, if fingers are vertically aligned and one is in the bottom zone,
  // consider that one a resting thumb (thus, do not scroll/right click)
  // if it has greater pressure. For clicking, we relax the pressure requirement
  // because we may not have enough time to determine.
  if (xdist < ydist && (FingerInDampenedZone(finger1) ||
                        FingerInDampenedZone(finger2)) &&
      (FingerInDampenedZone(finger1) == (finger1.pressure > finger2.pressure) ||
       check_button_type))
    return false;
  return true;
}

GestureType ImmediateInterpreter::GetTwoFingerGestureType(
    const FingerState& finger1,
    const FingerState& finger2) {
  if (!MapContainsKey(start_positions_, finger1.tracking_id) ||
      !MapContainsKey(start_positions_, finger2.tracking_id))
    return kGestureTypeNull;

  // If a finger is close to any thumb, we believe it to be due to thumb-splits
  // and ignore it.
  int num_close_to_thumb = 0;
  num_close_to_thumb += static_cast<int>(IsTooCloseToThumb(finger1));
  num_close_to_thumb += static_cast<int>(IsTooCloseToThumb(finger2));
  if (num_close_to_thumb == 1)
    return kGestureTypeMove;
  else if (num_close_to_thumb == 2)
    return kGestureTypeNull;

  // Compute distance traveled since fingers changed for each finger
  float dx1 = finger1.position_x - start_positions_[finger1.tracking_id].x_;
  float dy1 = finger1.position_y - start_positions_[finger1.tracking_id].y_;
  float dx2 = finger2.position_x - start_positions_[finger2.tracking_id].x_;
  float dy2 = finger2.position_y - start_positions_[finger2.tracking_id].y_;

  float large_dx = MaxMag(dx1, dx2);
  float large_dy = MaxMag(dy1, dy2);
  // These compares are okay if d{x,y}1 == d{x,y}2:
  short large_dx_id =
      large_dx == dx1 ? finger1.tracking_id : finger2.tracking_id;
  short large_dy_id =
      large_dy == dy1 ? finger1.tracking_id : finger2.tracking_id;
  float small_dx = MinMag(dx1, dx2);
  float small_dy = MinMag(dy1, dy2);

  bool dampened_zone_occupied = false;
  // movements of the finger in the dampened zone. If there are multiple
  // fingers in the dampened zone, dx is min(dx_1, dx_2), dy is min(dy_1, dy_2).
  float damp_dx = INFINITY;
  float damp_dy = INFINITY;
  float non_damp_dx = 0.0;
  float non_damp_dy = 0.0;
  bool damp_instaneous_moving_x = false;
  bool damp_instaneous_moving_y = false;
  if (FingerInDampenedZone(finger1) ||
      (finger1.flags & GESTURES_FINGER_POSSIBLE_PALM)) {
    dampened_zone_occupied = true;
    damp_dx = dx1;
    damp_dy = dy1;
    non_damp_dx = dx2;
    non_damp_dy = dy2;
    damp_instaneous_moving_x = damp_instaneous_moving_y =
        finger1.flags & GESTURES_FINGER_INSTANTANEOUS_MOVING;
  }
  if (FingerInDampenedZone(finger2) ||
      (finger2.flags & GESTURES_FINGER_POSSIBLE_PALM)) {
    dampened_zone_occupied = true;
    damp_dx = MinMag(damp_dx, dx2);
    damp_dy = MinMag(damp_dy, dy2);
    non_damp_dx = MaxMag(non_damp_dx, dx1);
    non_damp_dy = MaxMag(non_damp_dy, dy1);
    damp_instaneous_moving_x =
        damp_dx == dx1
            ? !!(finger1.flags & GESTURES_FINGER_INSTANTANEOUS_MOVING)
            : !!(finger2.flags & GESTURES_FINGER_INSTANTANEOUS_MOVING);
    damp_instaneous_moving_y =
        damp_dy == dy1
            ? !!(finger1.flags & GESTURES_FINGER_INSTANTANEOUS_MOVING)
            : !!(finger2.flags & GESTURES_FINGER_INSTANTANEOUS_MOVING);
  }

  // Trending in the same direction?
  const unsigned kTrendX =
      GESTURES_FINGER_TREND_INC_X | GESTURES_FINGER_TREND_DEC_X;
  const unsigned kTrendY =
      GESTURES_FINGER_TREND_INC_Y | GESTURES_FINGER_TREND_DEC_Y;
  unsigned common_trend_flags = finger1.flags & finger2.flags &
      (kTrendX | kTrendY);

  bool large_dx_moving =
      fabsf(large_dx) >= two_finger_scroll_distance_thresh_.val_ ||
      SetContainsValue(moving_, large_dx_id);
  bool large_dy_moving =
      fabsf(large_dy) >= two_finger_scroll_distance_thresh_.val_ ||
      SetContainsValue(moving_, large_dy_id);
  // We use a tighter moving criteria for damped finger here: it needs to be
  // moving in the past a few frames rather than just being moving before.
  bool small_dx_moving = fabsf(damp_dx) >=
      damp_scroll_min_movement_factor_.val_ * fabsf(non_damp_dx) ||
      damp_instaneous_moving_x;
  bool small_dy_moving = fabsf(damp_dy) >=
      damp_scroll_min_movement_factor_.val_ * fabsf(non_damp_dy) ||
      damp_instaneous_moving_y;
  // If not in damp zone, we allow one-finger scrolling
  bool small_dx_scrolling = !dampened_zone_occupied || small_dx_moving;
  bool small_dy_scrolling = !dampened_zone_occupied || small_dy_moving;
  bool trend_scrolling_x = (common_trend_flags & kTrendX) &&
       large_dx_moving && small_dx_scrolling;
  bool trend_scrolling_y = (common_trend_flags & kTrendY) &&
       large_dy_moving && small_dy_scrolling;

  if (trend_scrolling_x || trend_scrolling_y)
    return kGestureTypeScroll;

  if (fabsf(large_dx) > fabsf(large_dy)) {
    // consider horizontal scroll
    if (fabsf(large_dx) < two_finger_scroll_distance_thresh_.val_)
      return kGestureTypeNull;
    if (fabsf(small_dx) < scroll_stationary_finger_max_distance_.val_)
      small_dx = 0.0;
    if (large_dx * small_dx < 0.0)
      return kGestureTypeMove;  // not same direction
    if (dampened_zone_occupied) {
      // Require damp to move at least some amount with the other finger
      if (fabsf(damp_dx) <
          damp_scroll_min_movement_factor_.val_ * fabsf(non_damp_dx)) {
        return kGestureTypeMove;
      }
    }
    return kGestureTypeScroll;
  } else {
    // consider vertical scroll
    if (fabsf(large_dy) < two_finger_scroll_distance_thresh_.val_)
      return kGestureTypeNull;
    if (fabsf(small_dy) < scroll_stationary_finger_max_distance_.val_)
      small_dy = 0.0;
    if (large_dy * small_dy < 0.0)
      return kGestureTypeMove;
    if (dampened_zone_occupied) {
      // Require damp to move at least some amount with the other finger
      if (fabsf(damp_dy) <
          damp_scroll_min_movement_factor_.val_ * fabsf(non_damp_dy)) {
        return kGestureTypeMove;
      }
    }
    return kGestureTypeScroll;
  }
}

GestureType ImmediateInterpreter::GetThreeFingerGestureType(
    const FingerState* const fingers[3]) {
  const FingerState* x_fingers[] = { fingers[0], fingers[1], fingers[2] };
  const FingerState* y_fingers[] = { fingers[0], fingers[1], fingers[2] };
  qsort(x_fingers, 3, sizeof(*x_fingers), CompareX<FingerState>);
  qsort(y_fingers, 3, sizeof(*y_fingers), CompareY<FingerState>);

  bool horizontal =
      (x_fingers[2]->position_x - x_fingers[0]->position_x) >=
      (y_fingers[2]->position_y - y_fingers[0]->position_y);
  const FingerState* min_finger = horizontal ? x_fingers[0] : y_fingers[0];
  const FingerState* center_finger = horizontal ? x_fingers[1] : y_fingers[1];
  const FingerState* max_finger = horizontal ? x_fingers[2] : y_fingers[2];

  if (DistSq(*min_finger, *max_finger) >
      three_finger_close_distance_thresh_.val_ *
      three_finger_close_distance_thresh_.val_) {
    return kGestureTypeNull;
  }

  float dx[] = {
    min_finger->position_x - start_positions_[min_finger->tracking_id].x_,
    center_finger->position_x - start_positions_[center_finger->tracking_id].x_,
    max_finger->position_x - start_positions_[max_finger->tracking_id].x_
  };
  float dy[] = {
    min_finger->position_y - start_positions_[min_finger->tracking_id].y_,
    center_finger->position_y - start_positions_[center_finger->tracking_id].y_,
    max_finger->position_y - start_positions_[max_finger->tracking_id].y_
  };
  // pick horizontal or vertical
  float *deltas = fabsf(dx[0]) > fabsf(dy[0]) ? dx : dy;
  swipe_is_vertical_ = deltas == dy;

  // All three fingers must move in the same direction.
  if ((deltas[0] > 0 && !(deltas[1] > 0 && deltas[2] > 0)) ||
      (deltas[0] < 0 && !(deltas[1] < 0 && deltas[2] < 0))) {
    return kGestureTypeNull;
  }

  // One finger must have traveled far enough.
  if (fabsf(deltas[0]) < three_finger_swipe_distance_thresh_.val_ &&
      fabsf(deltas[1]) < three_finger_swipe_distance_thresh_.val_ &&
      fabsf(deltas[2]) < three_finger_swipe_distance_thresh_.val_) {
    return kGestureTypeNull;
  }

  return kGestureTypeSwipe;
}

const char* ImmediateInterpreter::TapToClickStateName(TapToClickState state) {
  switch (state) {
    case kTtcIdle: return "Idle";
    case kTtcFirstTapBegan: return "FirstTapBegan";
    case kTtcTapComplete: return "TapComplete";
    case kTtcSubsequentTapBegan: return "SubsequentTapBegan";
    case kTtcDrag: return "Drag";
    case kTtcDragRelease: return "DragRelease";
    case kTtcDragRetouch: return "DragRetouch";
    default: return "<unknown>";
  }
}

stime_t ImmediateInterpreter::TimeoutForTtcState(TapToClickState state) {
  switch (state) {
    case kTtcIdle: return tap_timeout_.val_;
    case kTtcFirstTapBegan: return tap_timeout_.val_;
    case kTtcTapComplete: return inter_tap_timeout_.val_;
    case kTtcSubsequentTapBegan: return tap_timeout_.val_;
    case kTtcDrag: return tap_timeout_.val_;
    case kTtcDragRelease: return tap_drag_timeout_.val_;
    case kTtcDragRetouch: return tap_timeout_.val_;
    default:
      Log("Unknown state!");
      return 0.0;
  }
}

void ImmediateInterpreter::SetTapToClickState(TapToClickState state,
                                              stime_t now) {
  if (tap_to_click_state_ != state) {
    tap_to_click_state_ = state;
    tap_to_click_state_entered_ = now;
  }
}

void ImmediateInterpreter::UpdateTapGesture(
    const HardwareState* hwstate,
    const FingerMap& gs_fingers,
    const bool same_fingers,
    stime_t now,
    stime_t* timeout) {
  unsigned down = 0;
  unsigned up = 0;
  UpdateTapState(hwstate, gs_fingers, same_fingers, now, &down, &up, timeout);
  if (down == 0 && up == 0) {
    return;
  }
  Log("UpdateTapGesture: Tap Generated");
  result_ = Gesture(kGestureButtonsChange,
                    state_buffer_.Get(1)->timestamp,
                    now,
                    down,
                    up);
}

void ImmediateInterpreter::UpdateTapState(
    const HardwareState* hwstate,
    const FingerMap& gs_fingers,
    const bool same_fingers,
    stime_t now,
    unsigned* buttons_down,
    unsigned* buttons_up,
    stime_t* timeout) {
  if (tap_to_click_state_ == kTtcIdle && (!tap_enable_.val_ ||
                                          tap_paused_.val_))
    return;

  FingerMap tap_gs_fingers;

  if (hwstate)
    RemoveMissingIdsFromSet(&tap_dead_fingers_, *hwstate);

  bool cancel_tapping = false;
  if (hwstate) {
    for (int i = 0; i < hwstate->finger_cnt; ++i) {
      if (hwstate->fingers[i].flags &
          (GESTURES_FINGER_NO_TAP | GESTURES_FINGER_MERGE))
        cancel_tapping = true;
    }
    for (FingerMap::const_iterator it =
             gs_fingers.begin(), e = gs_fingers.end(); it != e; ++it) {
      const FingerState* fs = hwstate->GetFingerState(*it);
      if (!fs) {
        Err("Missing finger state?!");
        continue;
      }
      tap_gs_fingers.insert(*it);
    }
  }
  set<short, kMaxTapFingers> added_fingers;

  // Fingers removed from the pad entirely
  set<short, kMaxTapFingers> removed_fingers;

  // Fingers that were gesturing, but now aren't
  set<short, kMaxFingers> dead_fingers;

  const bool phys_click_in_progress = hwstate && hwstate->buttons_down != 0 &&
    (zero_finger_click_enable_.val_ || finger_seen_shortly_after_button_down_);

  bool is_timeout = (now - tap_to_click_state_entered_ >
                     TimeoutForTtcState(tap_to_click_state_));

  if (phys_click_in_progress) {
    // Don't allow any current fingers to tap ever
    for (size_t i = 0; i < hwstate->finger_cnt; i++)
      tap_dead_fingers_.insert(hwstate->fingers[i].tracking_id);
  }

  if (hwstate && (!same_fingers || prev_tap_gs_fingers_ != tap_gs_fingers)) {
    // See if fingers were added
    for (FingerMap::const_iterator it =
             tap_gs_fingers.begin(), e = tap_gs_fingers.end(); it != e; ++it) {
      // If the finger was marked as a thumb before, it is not new.
      if (hwstate->timestamp - finger_origin_timestamp(*it) >
               thumb_click_prevention_timeout_.val_)
        continue;

      if (!SetContainsValue(prev_tap_gs_fingers_, *it)) {
        // Gesturing finger wasn't in prev state. It's new.
        const FingerState* fs = hwstate->GetFingerState(*it);
        if (FingerTooCloseToTap(*hwstate, *fs) ||
            FingerTooCloseToTap(*state_buffer_.Get(1), *fs) ||
            SetContainsValue(tap_dead_fingers_, fs->tracking_id))
          continue;
        added_fingers.insert(*it);
        Log("TTC: Added %d", *it);
      }
    }

    // See if fingers were removed or are now non-gesturing (dead)
    for (FingerMap::const_iterator it =
             prev_tap_gs_fingers_.begin(), e = prev_tap_gs_fingers_.end();
         it != e; ++it) {
      if (tap_gs_fingers.find(*it) != tap_gs_fingers.end())
        // still gesturing; neither removed nor dead
        continue;
      if (!hwstate->GetFingerState(*it)) {
        // Previously gesturing finger isn't in current state. It's gone.
        removed_fingers.insert(*it);
        Log("TTC: Removed %d", *it);
      } else {
        // Previously gesturing finger is in current state. It's dead.
        dead_fingers.insert(*it);
        Log("TTC: Dead %d", *it);
      }
    }
  }

  prev_tap_gs_fingers_ = tap_gs_fingers;

  // The state machine:

  // If you are updating the code, keep this diagram correct.
  // We have a TapRecord which stores current tap state.
  // Also, if the physical button is down or previous gesture type is scroll,
  // we go to (or stay in) Idle state.

  //     Start
  //       ↓
  //    [Idle**] <----------------------------------------------------------,
  //       ↓ added finger(s)                                                |
  //  ,>[FirstTapBegan] -<right click: send right click, timeout/movement>->|
  //  |    ↓ released all fingers                                           |
  // ,->[TapComplete*] --<timeout: send click>----------------------------->|
  // ||    | | two finger touching: send left click.                        |
  // |'----+-'                                                              |
  // |     ↓ add finger(s)                                                  |
  // |  [SubsequentTapBegan] --<timeout/move w/o delay: send click>-------->|
  // |     | | | release all fingers: send left click                       |
  // |<----+-+-'                                                            |
  // |     | `-> start non-left click: send left click; goto FirstTapBegan  |
  // |     ↓ timeout/movement with delay: send button down                  |
  // | ,->[Drag] --<detect 2 finger gesture: send button up>--------------->|
  // | |   ↓ release all fingers                                            |
  // | |  [DragRelease*]  --<timeout: send button up>---------------------->|
  // | |   ↓ add finger(s)                                                  |
  // | |  [DragRetouch]  --<remove fingers (left tap): send button up>----->|
  // | |   | | timeout/movement
  // | '---+-'
  // |     |  remove all fingers (non-left tap): send button up
  // '-----'
  //
  // * When entering TapComplete or DragRelease, we set a timer, since
  //   we will have no fingers on the pad and want to run possibly before
  //   fingers are put on the pad. Note that we use different timeouts
  //   based on which state we're in (tap_timeout_ or tap_drag_timeout_).
  // ** When entering idle, we reset the TapRecord.

  if (tap_to_click_state_ != kTtcIdle)
    Log("TTC State: %s", TapToClickStateName(tap_to_click_state_));
  if (!hwstate)
    Log("TTC: This is a timer callback");
  if (phys_click_in_progress || KeyboardRecentlyUsed(now) ||
      prev_result_.type == kGestureTypeScroll ||
      cancel_tapping) {
    Log("TTC: Forced to idle");
    SetTapToClickState(kTtcIdle, now);
    return;
  }

  switch (tap_to_click_state_) {
    case kTtcIdle:
      tap_record_.Clear();
      if (hwstate &&
          hwstate->timestamp - last_movement_timestamp_ >=
          motion_tap_prevent_timeout_.val_) {
        tap_record_.Update(
            *hwstate, *state_buffer_.Get(1), added_fingers, removed_fingers,
            dead_fingers);
        if (tap_record_.TapBegan())
          SetTapToClickState(kTtcFirstTapBegan, now);
      }
      break;
    case kTtcFirstTapBegan:
      if (is_timeout) {
        SetTapToClickState(kTtcIdle, now);
        break;
      }
      if (!hwstate) {
        Log("hwstate NULL but no timeout?!");
        break;
      }
      tap_record_.Update(
          *hwstate, *state_buffer_.Get(1), added_fingers,
          removed_fingers, dead_fingers);
      Log("TTC: Is tap? %d Is moving? %d",
          tap_record_.TapComplete(),
          tap_record_.Moving(*hwstate, tap_move_dist_.val_));
      if (tap_record_.TapComplete()) {
        if (!tap_record_.MinTapPressureMet() ||
            !tap_record_.FingersBelowMaxAge()) {
          SetTapToClickState(kTtcIdle, now);
        } else if (tap_record_.TapType() == GESTURES_BUTTON_LEFT &&
                   tap_drag_enable_.val_) {
          SetTapToClickState(kTtcTapComplete, now);
        } else {
          *buttons_down = *buttons_up = tap_record_.TapType();
          SetTapToClickState(kTtcIdle, now);
        }
      } else if (tap_record_.Moving(*hwstate, tap_move_dist_.val_)) {
        SetTapToClickState(kTtcIdle, now);
      }
      break;
    case kTtcTapComplete:
      if (!added_fingers.empty()) {

        tap_record_.Clear();
        tap_record_.Update(
            *hwstate, *state_buffer_.Get(1), added_fingers, removed_fingers,
            dead_fingers);

        // If more than one finger is touching: Send click
        // and return to FirstTapBegan state.
        if (tap_record_.TapType() != GESTURES_BUTTON_LEFT) {
          *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
          SetTapToClickState(kTtcFirstTapBegan, now);
        } else {
          tap_drag_last_motion_time_ = now;
          tap_drag_finger_was_stationary_ = false;
          SetTapToClickState(kTtcSubsequentTapBegan, now);
        }
      } else if (is_timeout) {
        *buttons_down = *buttons_up =
            tap_record_.MinTapPressureMet() ? tap_record_.TapType() : 0;
        SetTapToClickState(kTtcIdle, now);
      }
      break;
    case kTtcSubsequentTapBegan:
      if (!is_timeout && !hwstate) {
        Log("hwstate NULL but not a timeout?!");
        break;
      }
      if (hwstate)
        tap_record_.Update(*hwstate, *state_buffer_.Get(1), added_fingers,
                           removed_fingers, dead_fingers);

      if (!tap_record_.Motionless(*hwstate, *state_buffer_.Get(1),
                                  tap_max_movement_.val_)) {
        tap_drag_last_motion_time_ = now;
      }
      if (tap_record_.TapType() == GESTURES_BUTTON_LEFT &&
          now - tap_drag_last_motion_time_ > tap_drag_stationary_time_.val_) {
        tap_drag_finger_was_stationary_ = true;
      }

      if (is_timeout || tap_record_.Moving(*hwstate, tap_move_dist_.val_)) {
        if (tap_record_.TapType() == GESTURES_BUTTON_LEFT) {
          if (is_timeout) {
            // moving with just one finger. Start dragging.
            *buttons_down = GESTURES_BUTTON_LEFT;
            SetTapToClickState(kTtcDrag, now);
          } else {
            bool drag_delay_met = (now - tap_to_click_state_entered_
                                   > tap_drag_delay_.val_);
            if (drag_delay_met && tap_drag_finger_was_stationary_) {
              *buttons_down = GESTURES_BUTTON_LEFT;
              SetTapToClickState(kTtcDrag, now);
            } else {
              *buttons_down = GESTURES_BUTTON_LEFT;
              *buttons_up = GESTURES_BUTTON_LEFT;
              SetTapToClickState(kTtcIdle, now);
            }
          }
        } else if (!tap_record_.TapComplete()) {
          // not just one finger. Send button click and go to idle.
          *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
          SetTapToClickState(kTtcIdle, now);
        }
        break;
      }
      if (tap_record_.TapType() != GESTURES_BUTTON_LEFT) {
        // We aren't going to drag, so send left click now and handle current
        // tap afterwards.
        *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
        SetTapToClickState(kTtcFirstTapBegan, now);
      }
      if (tap_record_.TapComplete()) {
        *buttons_down = *buttons_up = GESTURES_BUTTON_LEFT;
        SetTapToClickState(kTtcTapComplete, now);
        Log("TTC: Subsequent left tap complete");
      }
      break;
    case kTtcDrag:
      if (hwstate)
        tap_record_.Update(
            *hwstate, *state_buffer_.Get(1), added_fingers, removed_fingers,
            dead_fingers);
      if (tap_record_.TapComplete()) {
        tap_record_.Clear();
        if (drag_lock_enable_.val_) {
          SetTapToClickState(kTtcDragRelease, now);
        } else {
          *buttons_up = GESTURES_BUTTON_LEFT;
          SetTapToClickState(kTtcIdle, now);
        }
      }
      if (tap_record_.TapType() != GESTURES_BUTTON_LEFT &&
          now - tap_to_click_state_entered_ <= evaluation_timeout_.val_) {
        // We thought we were dragging, but actually we're doing a
        // non-tap-to-click multitouch gesture.
        *buttons_up = GESTURES_BUTTON_LEFT;
        SetTapToClickState(kTtcIdle, now);
      }
      break;
    case kTtcDragRelease:
      if (!added_fingers.empty()) {
        tap_record_.Update(
            *hwstate, *state_buffer_.Get(1), added_fingers, removed_fingers,
            dead_fingers);
        SetTapToClickState(kTtcDragRetouch, now);
      } else if (is_timeout) {
        *buttons_up = GESTURES_BUTTON_LEFT;
        SetTapToClickState(kTtcIdle, now);
      }
      break;
    case kTtcDragRetouch:
      if (hwstate)
        tap_record_.Update(
            *hwstate, *state_buffer_.Get(1), added_fingers, removed_fingers,
            dead_fingers);
      if (tap_record_.TapComplete()) {
        *buttons_up = GESTURES_BUTTON_LEFT;
        if (tap_record_.TapType() == GESTURES_BUTTON_LEFT)
          SetTapToClickState(kTtcIdle, now);
        else
          SetTapToClickState(kTtcTapComplete, now);
        break;
      }
      if (is_timeout) {
        SetTapToClickState(kTtcDrag, now);
        break;
      }
      if (!hwstate) {
        Log("not timeout but hwstate is NULL?!");
        break;
      }
      if (tap_record_.Moving(*hwstate, tap_move_dist_.val_))
        SetTapToClickState(kTtcDrag, now);
      break;
  }
  if (tap_to_click_state_ != kTtcIdle)
    Log("TTC: New state: %s", TapToClickStateName(tap_to_click_state_));
  // Take action based on new state:
  switch (tap_to_click_state_) {
    case kTtcTapComplete:
      *timeout = TimeoutForTtcState(tap_to_click_state_);
      break;
    case kTtcDragRelease:
      *timeout = TimeoutForTtcState(tap_to_click_state_);
      break;
    default:  // so gcc doesn't complain about missing enums
      break;
  }
}

bool ImmediateInterpreter::FingerTooCloseToTap(const HardwareState& hwstate,
                                               const FingerState& fs) {
  const float kMinAllowableSq =
      tapping_finger_min_separation_.val_ * tapping_finger_min_separation_.val_;
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    const FingerState* iter_fs = &hwstate.fingers[i];
    if (iter_fs->tracking_id == fs.tracking_id)
      continue;
    float dist_sq = DistSq(fs, *iter_fs);
    if (dist_sq < kMinAllowableSq)
      return true;
  }
  return false;
}

bool ImmediateInterpreter::FingerInDampenedZone(
    const FingerState& finger) const {
  // TODO(adlr): cache thresh
  float thresh = hwprops_->bottom - bottom_zone_size_.val_;
  return finger.position_y > thresh;
}

void ImmediateInterpreter::FillStartPositions(const HardwareState& hwstate) {
  RemoveMissingIdsFromMap(&origin_positions_, hwstate);

  for (short i = 0; i < hwstate.finger_cnt; i++) {
    Point point(hwstate.fingers[i].position_x,
                hwstate.fingers[i].position_y);
    start_positions_[hwstate.fingers[i].tracking_id] = point;
    if (!MapContainsKey(origin_positions_, hwstate.fingers[i].tracking_id))
      origin_positions_[hwstate.fingers[i].tracking_id] = point;
  }
}

int ImmediateInterpreter::GetButtonTypeFromPosition(
    const HardwareState& hwstate) {
  if (hwstate.finger_cnt <= 0 || hwstate.finger_cnt > 1 ||
      !button_right_click_zone_enable_.val_) {
    return GESTURES_BUTTON_LEFT;
  }

  const FingerState& fs = hwstate.fingers[0];
  if (fs.position_x > hwprops_->right - button_right_click_zone_size_.val_) {
    return GESTURES_BUTTON_RIGHT;
  }

  return GESTURES_BUTTON_LEFT;
}

int ImmediateInterpreter::EvaluateButtonType(
    const HardwareState& hwstate, stime_t button_down_time) {
  // Handle T5R2/SemiMT touchpads
  if ((hwprops_->supports_t5r2 || hwprops_->support_semi_mt) &&
      hwstate.touch_cnt > 2) {
    if (hwstate.touch_cnt - thumb_.size() == 3 &&
        three_finger_click_enable_.val_ && t5r2_three_finger_click_enable_.val_)
      return GESTURES_BUTTON_MIDDLE;
    return GESTURES_BUTTON_RIGHT;
  }

  // Just return the hardware state button, based on finger position,
  // if no further analysis is needed.
  bool finger_update = finger_button_click_.Update(hwstate, button_down_time);
  if (!finger_update && hwprops_->is_button_pad &&
      hwstate.buttons_down == GESTURES_BUTTON_LEFT) {
    return GetButtonTypeFromPosition(hwstate);
  } else if (!finger_update) {
    return hwstate.buttons_down;
  }
  Log("EvaluateButtonType: R/C/H: %d/%d/%d",
      finger_button_click_.num_recent(),
      finger_button_click_.num_cold(),
      finger_button_click_.num_hot());

  // Handle 2 finger cases:
  if (finger_button_click_.num_fingers() == 2)
    return finger_button_click_.EvaluateTwoFingerButtonType();

  // Handle cases with 3 or more fingers:
  return finger_button_click_.EvaluateThreeOrMoreFingerButtonType();
}

FingerMap ImmediateInterpreter::UpdateMovingFingers(
    const HardwareState& hwstate) {
  FingerMap newly_moving_fingers;
  if (moving_.size() == hwstate.finger_cnt)
    return newly_moving_fingers;  // All fingers already started moving
  const float kMinDistSq =
      change_move_distance_.val_ * change_move_distance_.val_;
  for (size_t i = 0; i < hwstate.finger_cnt; i++) {
    const FingerState& fs = hwstate.fingers[i];
    if (!MapContainsKey(start_positions_, fs.tracking_id)) {
      Err("Missing start position!");
      continue;
    }
    if (SetContainsValue(moving_, fs.tracking_id)) {
      // This finger already moving
      continue;
    }
    float dist_sq = DistanceTravelledSq(fs, false);
    if (dist_sq > kMinDistSq) {
      moving_.insert(fs.tracking_id);
      newly_moving_fingers.insert(fs.tracking_id);
    }
  }
  return newly_moving_fingers;
}

void ImmediateInterpreter::UpdateStartedMovingTime(
    stime_t now,
    const FingerMap& gs_fingers,
    const FingerMap& newly_moving_fingers) {
  // Update started moving time if any gesturing finger is newly moving.
  for (auto it = gs_fingers.begin(), e = gs_fingers.end(); it != e; ++it) {
    if (SetContainsValue(newly_moving_fingers, *it)) {
      started_moving_time_ = now;
      // Extend the thumb evaluation period for any finger that is still under
      // evaluation as there is a new moving finger.
      for (map<short, stime_t, kMaxFingers>::iterator it = thumb_.begin();
           it != thumb_.end(); ++it)
        if ((*it).second < thumb_eval_timeout_.val_ && (*it).second > 0.0)
          (*it).second = thumb_eval_timeout_.val_;
      return;
    }
  }
}

void ImmediateInterpreter::UpdateButtons(const HardwareState& hwstate,
                                         stime_t* timeout) {
  // TODO(miletus): To distinguish between left/right buttons down
  bool prev_button_down = state_buffer_.Get(1)->buttons_down;
  bool button_down = hwstate.buttons_down;
  if (!prev_button_down && !button_down)
    return;
  bool phys_down_edge = button_down && !prev_button_down;
  bool phys_up_edge = !button_down && prev_button_down;
  if (phys_down_edge) {
    finger_seen_shortly_after_button_down_ = false;
    sent_button_down_ = false;
    button_down_timeout_ = hwstate.timestamp + button_evaluation_timeout_.val_;
  }

  // If we haven't seen a finger on the pad shortly after the click, do nothing
  if (!finger_seen_shortly_after_button_down_ &&
      hwstate.timestamp <= button_down_timeout_)
    finger_seen_shortly_after_button_down_ = (hwstate.finger_cnt > 0);
  if (!finger_seen_shortly_after_button_down_ &&
      !zero_finger_click_enable_.val_)
    return;

  if (!sent_button_down_) {
    stime_t button_down_time = button_down_timeout_ -
                               button_evaluation_timeout_.val_;
    button_type_ = EvaluateButtonType(hwstate, button_down_time);

    if (!hwstate.SameFingersAs(*state_buffer_.Get(0))) {
      // Fingers have changed since last state, reset timeout
      button_down_timeout_ = hwstate.timestamp + button_finger_timeout_.val_;
    }

    // button_up before button_evaluation_timeout_ expired.
    // Send up & down for button that was previously down, but not yet sent.
    if (button_type_ == GESTURES_BUTTON_NONE)
      button_type_ = prev_button_down;
    // Send button down if timeout has been reached or button up happened
    if (button_down_timeout_ <= hwstate.timestamp ||
        phys_up_edge) {
      // Send button down
      if (result_.type == kGestureTypeButtonsChange)
        Err("Gesture type already button?!");
      result_ = Gesture(kGestureButtonsChange,
                        state_buffer_.Get(1)->timestamp,
                        hwstate.timestamp,
                        button_type_,
                        0);
      sent_button_down_ = true;
    } else if (timeout) {
      *timeout = button_down_timeout_ - hwstate.timestamp;
    }
  }
  if (phys_up_edge) {
    // Send button up
    if (result_.type != kGestureTypeButtonsChange)
      result_ = Gesture(kGestureButtonsChange,
                        state_buffer_.Get(1)->timestamp,
                        hwstate.timestamp,
                        0,
                        button_type_);
    else
      result_.details.buttons.up = button_type_;
    // Reset button state
    button_type_ = GESTURES_BUTTON_NONE;
    button_down_timeout_ = 0;
    sent_button_down_ = false;
    // When a buttons_up event is generated, we need to reset the
    // finger_leave_time_ in order to defer any gesture generation
    // right after it.
    finger_leave_time_ = hwstate.timestamp;
  }
}

void ImmediateInterpreter::UpdateButtonsTimeout(stime_t now) {
  if (sent_button_down_) {
    Err("How is sent_button_down_ set?");
    return;
  }
  if (button_type_ == GESTURES_BUTTON_NONE)
    return;
  sent_button_down_ = true;
  result_ = Gesture(kGestureButtonsChange,
                    state_buffer_.Get(1)->timestamp,
                    now,
                    button_type_,
                    0);
}

void ImmediateInterpreter::FillResultGesture(
    const HardwareState& hwstate,
    const FingerMap& fingers) {
  switch (current_gesture_type_) {
    case kGestureTypeMove: {
      if (fingers.empty())
        return;
      // Use highest finger (the one closes to the keyboard), excluding
      // palms, to compute motion. First, need to find out which finger that is.
      const FingerState* current = NULL;
      if (moving_finger_id_ >= 0)
        current = hwstate.GetFingerState(moving_finger_id_);

      if (!current) {
        for (FingerMap::const_iterator it =
                 fingers.begin(), e = fingers.end(); it != e; ++it) {
          const FingerState* fs = hwstate.GetFingerState(*it);
          if (!current || fs->position_y < current->position_y ||
              (current->flags & GESTURES_FINGER_POSSIBLE_PALM &&
               !(fs->flags & GESTURES_FINGER_POSSIBLE_PALM)))
            current = fs;
        }
      }

      // Find corresponding finger id in previous state
      const FingerState* prev =
          state_buffer_.Get(1)->GetFingerState(current->tracking_id);
      const FingerState* prev2 = !state_buffer_.Get(2) ? NULL :
          state_buffer_.Get(2)->GetFingerState(current->tracking_id);
      if (!prev || !current)
        return;
      if (current->flags & GESTURES_FINGER_MERGE)
        return;
      stime_t dt = hwstate.timestamp - state_buffer_.Get(1)->timestamp;
      bool suppress_finger_movement =
          scroll_manager_.SuppressStationaryFingerMovement(
              *current, *prev, dt) ||
          scroll_manager_.StationaryFingerPressureChangingSignificantly(
              state_buffer_, *current);
      if (quick_acceleration_factor_.val_ && prev2) {
        stime_t dt2 =
            state_buffer_.Get(1)->timestamp - state_buffer_.Get(2)->timestamp;
        float dist_sq = DistSq(*current, *prev);
        float dist_sq2 = DistSq(*prev, *prev2);
        if (dist_sq2 * dt &&  // have prev dist and current time
            dist_sq2 * dt * dt *
            quick_acceleration_factor_.val_ * quick_acceleration_factor_.val_ <
            dist_sq * dt2 * dt2) {
          return;
        }
      }
      if (suppress_finger_movement) {
        scroll_manager_.prev_result_suppress_finger_movement_ = true;
        return;
      }
      scroll_manager_.prev_result_suppress_finger_movement_ = false;
      float dx = current->position_x - prev->position_x;
      if (current->flags & GESTURES_FINGER_WARP_X_MOVE)
        dx = 0.0;
      float dy = current->position_y - prev->position_y;
      if (current->flags & GESTURES_FINGER_WARP_Y_MOVE)
        dy = 0.0;
      if (dx != 0.0 || dy != 0.0) {
        // lock onto this finger
        moving_finger_id_ = current->tracking_id;

        result_ = Gesture(kGestureMove,
                          state_buffer_.Get(1)->timestamp,
                          hwstate.timestamp,
                          dx,
                          dy);
      }
      break;
    }
    case kGestureTypeScroll: {
      if (!scroll_manager_.ComputeScroll(state_buffer_,
                                         prev_active_gs_fingers_,
                                         fingers,
                                         prev_gesture_type_,
                                         prev_result_,
                                         &result_,
                                         &scroll_buffer_))
        return;
      break;
    }
    case kGestureTypeFling: {
      scroll_manager_.ComputeFling(state_buffer_, scroll_buffer_, &result_);
      break;
    }
    case kGestureTypeSwipe: {
      if (!three_finger_swipe_enable_.val_)
        break;
      float sum_delta[] = { 0.0, 0.0 };
      bool valid[] = { true, true };
      float finger_cnt[] = { 0.0, 0.0 };
      float FingerState::*fields[] = { &FingerState::position_x,
                                       &FingerState::position_y };
      for (FingerMap::const_iterator it =
               fingers.begin(), e = fingers.end(); it != e; ++it) {
        if (!state_buffer_.Get(1)->GetFingerState(*it)) {
          Err("missing prev state?");
          continue;
        }
        // We have this loop in case we want to compute diagonal swipes at
        // some point, even if currently we go with just one axis.
        for (size_t i = 0; i < arraysize(fields); i++) {
          bool correct_axis = (i == 1) == swipe_is_vertical_;
          if (!valid[i] || !correct_axis)
            continue;
          float FingerState::*field = fields[i];
          float delta = hwstate.GetFingerState(*it)->*field -
              state_buffer_.Get(1)->GetFingerState(*it)->*field;
          // The multiply is to see if they have the same sign:
          if (sum_delta[i] == 0.0 || sum_delta[i] * delta > 0) {
            sum_delta[i] += delta;
            finger_cnt[i] += 1.0;
          } else {
            sum_delta[i] = 0.0;
            valid[i] = false;
          }
        }
      }
      result_ = Gesture(
          kGestureSwipe, state_buffer_.Get(1)->timestamp,
          hwstate.timestamp,
          (!swipe_is_vertical_ && finger_cnt[0]) ?
          sum_delta[0] / finger_cnt[0] : 0.0,
          (swipe_is_vertical_ && finger_cnt[1]) ?
          sum_delta[1] / finger_cnt[1] : 0.0);
      break;
    }
    case kGestureTypeSwipeLift: {
      result_ = Gesture(kGestureSwipeLift,
                        state_buffer_.Get(1)->timestamp,
                        hwstate.timestamp);
      break;
    }

    case kGestureTypePinch: {
      float current_dist = sqrtf(TwoFingerDistanceSq(hwstate));
      result_ = Gesture(kGesturePinch, changed_time_, hwstate.timestamp,
                        current_dist / two_finger_start_distance_);
      break;
    }
    default:
      result_.type = kGestureTypeNull;
  }
  scroll_manager_.UpdateScrollEventBuffer(current_gesture_type_,
                                          &scroll_buffer_);
  if (result_.type == kGestureTypeMove ||
      result_.type == kGestureTypeScroll)
    last_movement_timestamp_ = hwstate.timestamp;
}

void ImmediateInterpreter::IntWasWritten(IntProperty* prop) {
  if (prop == &keyboard_touched_timeval_low_) {
    struct timeval tv = {
      keyboard_touched_timeval_high_.val_,
      keyboard_touched_timeval_low_.val_
    };
    keyboard_touched_ = StimeFromTimeval(&tv);
  }
}

void ImmediateInterpreter::Initialize(const HardwareProperties* hwprops,
                                      Metrics* metrics,
                                      MetricsProperties* mprops,
                                      GestureConsumer* consumer) {
  Interpreter::Initialize(hwprops, metrics, mprops, consumer);
  state_buffer_.Reset(hwprops_->max_finger_cnt);
}

bool AnyGesturingFingerLeft(const HardwareState& state,
                            const FingerMap& prev_gs_fingers) {
  for (FingerMap::const_iterator it = prev_gs_fingers.begin(),
                                 e = prev_gs_fingers.end(); it != e; ++it) {
    if (!state.GetFingerState(*it)) {
      return true;
    }
  }
  return false;
}

}  // namespace gestures
