/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/* eslint-disable */

'use strict'

var isInitialized = false

// major events supported:
//   panstart
//   panmove
//   panend
//   swipe
//   longpress
// extra events supported:
//   dualtouchstart
//   dualtouch
//   dualtouchend
//   tap
//   doubletap
//   pressend

var doc = window.document
var docEl = doc.documentElement
var slice = Array.prototype.slice
var gestures = {}
var lastTap = null

/**
 * find the closest common ancestor
 * if there's no one, return null
 *
 * @param  {Element} el1 first element
 * @param  {Element} el2 second element
 * @return {Element}     common ancestor
 */
function getCommonAncestor(el1, el2) {
  var el = el1
  while (el) {
    if (el.contains(el2) || el == el2) {
      return el
    }
    el = el.parentNode
  }
  return null
}

/**
 * fire a HTMLEvent
 *
 * @param  {Element} element which element to fire a event on
 * @param  {string}  type    type of event
 * @param  {object}  extra   extra data for the event object
 */
function fireEvent(element, type, extra) {
  var event = doc.createEvent('HTMLEvents')
  event.initEvent(type, true, true)

  if (typeof extra === 'object') {
    for (var p in extra) {
      event[p] = extra[p]
    }
  }

  /**
   * A flag to distinguish with other events with the same name generated
   * by another library in the same page.
   */ 
  event._for = 'weex'

  element.dispatchEvent(event)
}

/**
 * calc the transform
 * assume 4 points ABCD on the coordinate system
 * > rotate：angle rotating from AB to CD
 * > scale：scale ratio from AB to CD
 * > translate：translate shift from A to C
 *
 * @param  {number} x1 abscissa of A
 * @param  {number} y1 ordinate of A
 * @param  {number} x2 abscissa of B
 * @param  {number} y2 ordinate of B
 * @param  {number} x3 abscissa of C
 * @param  {number} y3 ordinate of C
 * @param  {number} x4 abscissa of D
 * @param  {number} y4 ordinate of D
 * @return {object}    transform object like
 *   {rotate, scale, translate[2], matrix[3][3]}
 */
function calc(x1, y1, x2, y2, x3, y3, x4, y4) {
  var rotate = Math.atan2(y4 - y3, x4 - x3) - Math.atan2(y2 - y1, x2 - x1)
  var scale = Math.sqrt((Math.pow(y4 - y3, 2)
    + Math.pow(x4 - x3, 2)) / (Math.pow(y2 - y1, 2)
    + Math.pow(x2 - x1, 2)))
  var translate = [
    x3
    - scale * x1 * Math.cos(rotate)
    + scale * y1 * Math.sin(rotate),
    y3
    - scale * y1 * Math.cos(rotate)
    - scale * x1 * Math.sin(rotate)]

  return {
    rotate: rotate,
    scale: scale,
    translate: translate,
    matrix: [
      [scale * Math.cos(rotate), -scale * Math.sin(rotate), translate[0]],
      [scale * Math.sin(rotate), scale * Math.cos(rotate), translate[1]],
      [0, 0, 1]
    ]
  }
}

/**
 * take over the touchstart events. Add new touches to the gestures.
 * If there is no previous records, then bind touchmove, tochend
 * and touchcancel events.
 * new touches initialized with state 'tapping', and within 500 milliseconds
 * if the state is still tapping, then trigger gesture 'press'.
 * If there are two touche points, then the 'dualtouchstart' is triggerd. The
 * node of the touch gesture is their cloest common ancestor.
 *
 * @event
 * @param  {event} event
 */
function touchstartHandler(event) {

  if (Object.keys(gestures).length === 0) {
    docEl.addEventListener('touchmove', touchmoveHandler, false)
    docEl.addEventListener('touchend', touchendHandler, false)
    docEl.addEventListener('touchcancel', touchcancelHandler, false)
  }

  // record every touch
  for (var i = 0; i < event.changedTouches.length; i++) {
    var touch = event.changedTouches[i]
    var touchRecord = {}

    for (var p in touch) {
      touchRecord[p] = touch[p]
    }

    var gesture = {
      startTouch: touchRecord,
      startTime: Date.now(),
      status: 'tapping',
      element: event.srcElement || event.target,
      pressingHandler: setTimeout(function (element, touch) {
        return function () {
          if (gesture.status === 'tapping') {
            gesture.status = 'pressing'

            fireEvent(element, 'longpress', {
              // add touch data for weex
              touch: touch,
              touches: event.touches,
              changedTouches: event.changedTouches,
              touchEvent: event
            })
          }

          clearTimeout(gesture.pressingHandler)
          gesture.pressingHandler = null
        }
      }(event.srcElement || event.target, event.changedTouches[i]), 500)
    }
    gestures[touch.identifier] = gesture
  }

  if (Object.keys(gestures).length == 2) {
    var elements = []

    for (var p in gestures) {
      elements.push(gestures[p].element)
    }

    fireEvent(getCommonAncestor(elements[0], elements[1]), 'dualtouchstart', {
      touches: slice.call(event.touches),
      touchEvent: event
    })
  }
}

/**
 * take over touchmove events, and handle pan and dual related gestures.
 *
 * 1. traverse every touch point：
 * > if 'tapping' and the shift is over 10 pixles, then it's a 'panning'.
 * 2. if there are two touch points, then calc the tranform and trigger
 *   'dualtouch'.
 *
 * @event
 * @param  {event} event
 */
function touchmoveHandler(event) {
  for (var i = 0; i < event.changedTouches.length; i++) {
    var touch = event.changedTouches[i]
    var gesture = gestures[touch.identifier]

    if (!gesture) {
      return
    }

    if (!gesture.lastTouch) {
      gesture.lastTouch = gesture.startTouch
    }
    if (!gesture.lastTime) {
      gesture.lastTime = gesture.startTime
    }
    if (!gesture.velocityX) {
      gesture.velocityX = 0
    }
    if (!gesture.velocityY) {
      gesture.velocityY = 0
    }
    if (!gesture.duration) {
      gesture.duration = 0
    }

    var time =  Date.now() - gesture.lastTime
    var vx = (touch.clientX - gesture.lastTouch.clientX) / time
    var vy = (touch.clientY - gesture.lastTouch.clientY) / time

    var RECORD_DURATION = 70
    if (time > RECORD_DURATION) {
      time = RECORD_DURATION
    }
    if (gesture.duration + time > RECORD_DURATION) {
      gesture.duration = RECORD_DURATION - time
    }

    gesture.velocityX = (gesture.velocityX * gesture.duration + vx * time)
      / (gesture.duration + time)
    gesture.velocityY = (gesture.velocityY * gesture.duration + vy * time)
      / (gesture.duration + time)
    gesture.duration += time

    gesture.lastTouch = {}

    for (var p in touch) {
      gesture.lastTouch[p] = touch[p]
    }
    gesture.lastTime = Date.now()

    var displacementX = touch.clientX - gesture.startTouch.clientX
    var displacementY = touch.clientY - gesture.startTouch.clientY
    var distance = Math.sqrt(Math.pow(displacementX, 2)
      + Math.pow(displacementY, 2))
    var isVertical = !(Math.abs(displacementX) > Math.abs(displacementY))
    var direction = isVertical
      ? displacementY >= 0 ? 'down' : 'up'
      : displacementX >= 0 ? 'right' : 'left'

    // magic number 10: moving 10px means pan, not tap
    if ((gesture.status === 'tapping' || gesture.status === 'pressing')
        && distance > 10) {
      gesture.status = 'panning'
      gesture.isVertical = isVertical
      gesture.direction = direction

      fireEvent(gesture.element, 'panstart', {
        touch: touch,
        touches: event.touches,
        changedTouches: event.changedTouches,
        touchEvent: event,
        isVertical: gesture.isVertical,
        direction: direction
      })
    }

    if (gesture.status === 'panning') {
      gesture.panTime = Date.now()

      fireEvent(gesture.element, 'panmove', {
        displacementX: displacementX,
        displacementY: displacementY,
        touch: touch,
        touches: event.touches,
        changedTouches: event.changedTouches,
        touchEvent: event,
        isVertical: gesture.isVertical,
        direction: direction
      })
    }
  }

  if (Object.keys(gestures).length == 2) {
    var position = []
    var current = []
    var elements = []
    var transform

    for (var i = 0; i < event.touches.length; i++) {
      var touch = event.touches[i]
      var gesture = gestures[touch.identifier]
      position.push([gesture.startTouch.clientX, gesture.startTouch.clientY])
      current.push([touch.clientX, touch.clientY])
    }

    for (var p in gestures) {
      elements.push(gestures[p].element)
    }

    transform = calc(
      position[0][0],
      position[0][1],
      position[1][0],
      position[1][1],
      current[0][0],
      current[0][1],
      current[1][0],
      current[1][1]
    )
    fireEvent(getCommonAncestor(elements[0], elements[1]), 'dualtouch', {
      transform: transform,
      touches: event.touches,
      touchEvent: event
    })
  }
}

/**
 * handle touchend event
 *
 * 1. if there are tow touch points, then trigger 'dualtouchend'如
 *
 * 2. traverse every touch piont：
 * > if tapping, then trigger 'tap'.
 * If there is a tap 300 milliseconds before, then it's a 'doubletap'.
 * > if padding, then decide to trigger 'panend' or 'swipe'
 * > if pressing, then trigger 'pressend'.
 *
 * 3. remove listeners.
 *
 * @event
 * @param  {event} event
 */
function touchendHandler(event) {

  if (Object.keys(gestures).length == 2) {
    var elements = []
    for (var p in gestures) {
      elements.push(gestures[p].element)
    }
    fireEvent(getCommonAncestor(elements[0], elements[1]), 'dualtouchend', {
      touches: slice.call(event.touches),
      touchEvent: event
    })
  }

  for (var i = 0; i < event.changedTouches.length; i++) {
    var touch = event.changedTouches[i]
    var id = touch.identifier
    var gesture = gestures[id]

    if (!gesture) {
      continue
    }

    if (gesture.pressingHandler) {
      clearTimeout(gesture.pressingHandler)
      gesture.pressingHandler = null
    }

    if (gesture.status === 'tapping') {
      gesture.timestamp = Date.now()
      // fire click, not tap.
      fireEvent(gesture.element, 'tap', {
        touch: touch,
        touchEvent: event
      })

      if (lastTap && gesture.timestamp - lastTap.timestamp < 300) {
        fireEvent(gesture.element, 'doubletap', {
          touch: touch,
          touchEvent: event
        })
      }

      lastTap = gesture
    }

    if (gesture.status === 'panning') {
      var now = Date.now()
      var duration = now - gesture.startTime
      var displacementX = touch.clientX - gesture.startTouch.clientX
      var displacementY = touch.clientY - gesture.startTouch.clientY

      var velocity = Math.sqrt(gesture.velocityY * gesture.velocityY
        + gesture.velocityX * gesture.velocityX)
      var isSwipe = velocity > 0.5 && (now - gesture.lastTime) < 100
      var extra = {
        duration: duration,
        isSwipe: isSwipe,
        velocityX: gesture.velocityX,
        velocityY: gesture.velocityY,
        displacementX: displacementX,
        displacementY: displacementY,
        touch: touch,
        touches: event.touches,
        changedTouches: event.changedTouches,
        touchEvent: event,
        isVertical: gesture.isVertical,
        direction: gesture.direction
      }

      fireEvent(gesture.element, 'panend', extra)
      if (isSwipe) {
        fireEvent(gesture.element, 'swipe', extra)
      }
    }

    if (gesture.status === 'pressing') {
      fireEvent(gesture.element, 'pressend', {
        touch: touch,
        touchEvent: event
      })
    }

    delete gestures[id]
  }

  if (Object.keys(gestures).length === 0) {
    docEl.removeEventListener('touchmove', touchmoveHandler, false)
    docEl.removeEventListener('touchend', touchendHandler, false)
    docEl.removeEventListener('touchcancel', touchcancelHandler, false)
  }
}

/**
 * handle touchcancel
 *
 * 1. if there are two touch points, then trigger 'dualtouchend'
 *
 * 2. traverse everty touch point:
 * > if pannnig, then trigger 'panend'
 * > if pressing, then trigger 'pressend'
 *
 * 3. remove listeners
 *
 * @event
 * @param  {event} event
 */
function touchcancelHandler(event) {

  if (Object.keys(gestures).length == 2) {
    var elements = []
    for (var p in gestures) {
      elements.push(gestures[p].element)
    }
    fireEvent(getCommonAncestor(elements[0], elements[1]), 'dualtouchend', {
      touches: slice.call(event.touches),
      touchEvent: event
    })
  }

  for (var i = 0; i < event.changedTouches.length; i++) {
    var touch = event.changedTouches[i]
    var id = touch.identifier
    var gesture = gestures[id]

    if (!gesture) {
      continue
    }

    if (gesture.pressingHandler) {
      clearTimeout(gesture.pressingHandler)
      gesture.pressingHandler = null
    }

    if (gesture.status === 'panning') {
      fireEvent(gesture.element, 'panend', {
        touch: touch,
        touches: event.touches,
        changedTouches: event.changedTouches,
        touchEvent: event
      })
    }
    if (gesture.status === 'pressing') {
      fireEvent(gesture.element, 'pressend', {
        touch: touch,
        touchEvent: event
      })
    }
    delete gestures[id]
  }

  if (Object.keys(gestures).length === 0) {
    docEl.removeEventListener('touchmove', touchmoveHandler, false)
    docEl.removeEventListener('touchend', touchendHandler, false)
    docEl.removeEventListener('touchcancel', touchcancelHandler, false)
  }
}

if (!isInitialized) {
  docEl.addEventListener('touchstart', touchstartHandler, false)
  isInitialized = true
}

