var time = use('time')
var audio = use('sound')
var math = use('math/radians')

var gesture = {}

gesture.MIN_SWIPE = 30
gesture.MAX_TIME = 500
gesture.PINCH_TH = 10

gesture.reset = function() {
  this.touches = {}  // Track active touches by finger id
  this.gestureState = null  // Current gesture being tracked
  this.startTime = 0
  this.startDist = 0
}

gesture.on_input = function(action_id, action) {
  if (search(action_id, 'gamepad_touchpad_') == null) return

  var finger = action.finger || 0
  var touchpad = action.touchpad || 0
  var fingerId = `${touchpad}_${finger}`
  var touchCount = 0
  var fingers = null
  var currentDist = 0
  var d = 0
  var gesture_type = null
  var touch = null
  var dt = 0
  var dx = 0
  var dy = 0
  var absX = 0
  var absY = 0
  var dir = null

  if (action_id == 'gamepad_touchpad_down') {
    // Add new touch
    this.touches[fingerId] = {
      x: action.x,
      y: action.y,
      startX: action.x,
      startY: action.y,
      startTime: time.number()
    }

    touchCount = length(array(this.touches))

    if (touchCount == 1) {
      // Single touch started
      this.gestureState = 'single'
      this.startTime = time.number()
    } else if (touchCount == 2) {
      // Two touches - potential pinch
      this.gestureState = 'multi'
      fingers = array(array(this.touches), k => this.touches[k])
      this.startDist = this.dist(fingers[0], fingers[1])
    }
  }
  else if (action_id == 'gamepad_touchpad_motion') {
    if (this.touches[fingerId]) {
      // Update touch position
      this.touches[fingerId].x = action.x
      this.touches[fingerId].y = action.y

      touchCount = length(array(this.touches))

      if (touchCount == 2 && this.gestureState == 'multi') {
        // Check for pinch gesture
        fingers = array(array(this.touches), k => this.touches[k])
        currentDist = this.dist(fingers[0], fingers[1])
        d = currentDist - this.startDist

        if (abs(d) >= this.PINCH_TH) {
          gesture_type = d > 0 ? 'pinch_out' : 'pinch_in'
//          scene.recurse(game.root, 'on_input', [gesture_type, { delta: d }])
          this.startDist = currentDist
        }
      }
    }
  }
  else if (action_id == 'gamepad_touchpad_up') {
    if (this.touches[fingerId]) {
      touch = this.touches[fingerId]
      touchCount = length(array(this.touches))

      // Check for swipe if this was the only/last touch
      if (touchCount == 1 && this.gestureState == 'single') {
        dt = time.number() - touch.startTime
        dx = action.x - touch.startX
        dy = action.y - touch.startY

        if (dt < this.MAX_TIME / 1000) { // Convert to seconds
          absX = abs(dx)
          absY = abs(dy)
          if (absX > this.MIN_SWIPE / 100 || absY > this.MIN_SWIPE / 100) { // Normalize for 0-1 range
            dir = absX > absY
                      ? (dx > 0 ? 'swipe_right' : 'swipe_left')
                      : (dy > 0 ? 'swipe_down' : 'swipe_up')
            audio.play('swipe')
//            scene.recurse(game.root, 'on_input', [dir, {pressed:true}])
          }
        }
      }

      // Remove touch
      delete this.touches[fingerId]

      // Reset if no touches left
      if (length(array(this.touches)) == 0) {
        this.gestureState = null
      }
    }
  }
}

gesture.dist = function(p1, p2) {
  var dx = p2.x - p1.x
  var dy = p2.y - p1.y
  return math.sqrt(math.power(dx, 2) + math.power(dy, 2))
}


return function(options) {
  var obj = meme(gesture)
  if (options) {
    obj.MIN_SWIPE = options.minSwipe || gesture.MIN_SWIPE
    obj.MAX_TIME = options.maxTime || gesture.MAX_TIME
    obj.PINCH_TH = options.pinchThreshold || gesture.PINCH_TH
  }
  obj.reset()
  return obj
}