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

#ifndef GESTURES_FINGER_METRICS_H_
#define GESTURES_FINGER_METRICS_H_

#include "gestures/include/gestures.h"
#include "gestures/include/prop_registry.h"
#include "gestures/include/vector.h"

namespace gestures {

static const size_t kMaxFingers = 10;
static const size_t kMaxGesturingFingers = 4;
static const size_t kMaxTapFingers = 10;

// A datastructure describing a 2D vector in the mathematical sense.
struct Vector2 {
  Vector2() : x(0), y(0) {}
  Vector2(float x, float y) : x(x), y(y) {}
  Vector2(const Vector2& other) : x(other.x), y(other.y) {}
  explicit Vector2(const FingerState& state) : x(state.position_x),
                                               y(state.position_y) {}

  Vector2 Sub(const Vector2& other) {
    return Vector2(x - other.x, y - other.y);
  }

  Vector2 Add(const Vector2& other) {
    return Vector2(x + other.x, y + other.y);
  }

  float MagSq() const {
    return x * x + y * y;
  }
  float Mag() const {
    return sqrtf(MagSq());
  }
  bool operator==(const Vector2& that) const {
    return x == that.x && y == that.y;
  }
  bool operator!=(const Vector2& that) const {
    return !(*this == that);
  }

  float x;
  float y;
};

extern Vector2 Add(const Vector2& left, const Vector2& right);
extern Vector2 Sub(const Vector2& left, const Vector2& right);
extern float Dot(const Vector2& left, const Vector2& right);

class MetricsProperties {
 public:
  explicit MetricsProperties(PropRegistry* prop_reg);

  // Maximum distance [mm] two fingers may be separated and still be eligible
  // for a two-finger gesture (e.g., scroll / tap / click). These define an
  // ellipse with horizontal and vertical axes lengths (think: radii).
  DoubleProperty two_finger_close_horizontal_distance_thresh;
  DoubleProperty two_finger_close_vertical_distance_thresh;
};

// This class describes a finger and derives additional metrics that
// are useful for gesture recognition.
// In contrast to a FingerState an instance of this class has the
// lifetime of the duration the finger touches the touchpad. This allows
// metrics to be derived from the history of a finger.
class FingerMetrics {
 public:
  FingerMetrics();
  explicit FingerMetrics(short tracking_id);
  FingerMetrics(const FingerState& state, MetricsProperties* properties,
                stime_t timestamp);

  // Update the finger metrics from a FingerState.
  // gesture_start: true if fingers have been added or removed during this
  //                sync.
  void Update(const FingerState& state, stime_t timestamp,
              bool gesture_start);

  short tracking_id() const { return tracking_id_; }

  // current position
  Vector2 position() const { return position_; }

  // position delta between current and last frame
  Vector2 delta() const { return delta_; }

  // origin is the time and position where the finger first touched
  Vector2 origin_position() const { return origin_position_; }
  stime_t origin_time() const { return origin_time_; }
  Vector2 origin_delta() const { return Sub(position_, origin_position_); }

  // start is the time and postion where the fingers were located
  // when the last of all current fingers touched (i.e. the gesture started)
  Vector2 start_position() const { return start_position_; }
  stime_t start_time() const { return start_time_; }
  Vector2 start_delta() const { return Sub(position_, start_position_); }

  // instances with the same tracking id are considered equal.
  bool operator==(const FingerMetrics& other) const {
    return other.tracking_id() == tracking_id_;
  }

 private:
  short tracking_id_;
  Vector2 position_;
  Vector2 delta_;
  Vector2 origin_position_;
  Vector2 start_position_;
  stime_t origin_time_;
  stime_t start_time_;
  MetricsProperties* properties_;
};

// The Metrics class is a container for FingerMetrics and additional
// metrics that are based on the interaction of multiple fingers.
// It is responsible for keeping the FingerMetrics instances updated
// with the latest FingerStates.
class Metrics {
 public:
  Metrics(MetricsProperties* properties);

  bool CloseEnoughToGesture(const Vector2& pos_a,
                            const Vector2& pos_b) const;

  // A collection of FingerMetrics describing the current hardware state.
  // The collection is sorted to yield the oldest finger first.
  vector<FingerMetrics, kMaxFingers>& fingers() { return fingers_; }

  // Find a FingerMetrics instance by it's tracking id.
  // Returns NULL if not found.
  FingerMetrics* GetFinger(short tracking_id) {
      return const_cast<FingerMetrics*>(
          const_cast<const Metrics*>(this)->GetFinger(tracking_id));
  }
  const FingerMetrics* GetFinger(short tracking_id) const;

  FingerMetrics* GetFinger(const FingerState& state);
  const FingerMetrics* GetFinger(const FingerState& state) const;

  // Update the collection of FingerMetrics using information from 'hwstate'.
  void Update(const HardwareState& hwstate);

  // Clear all finger information
  void Clear();

 private:
  vector<FingerMetrics, kMaxFingers> fingers_;

  MetricsProperties* properties_;
  std::unique_ptr<MetricsProperties> own_properties_;
};

}  // namespace gestures

#endif  // GESTURES_FINGER_METRICS_H_
