var _ = require('lodash')
var rotator = require('./rotator')
var ImagePool = require('./imagepool')
var imageFile = require('./imagefile')

module.exports = function DeviceScreenDirective(
  $document
, ScalingService
, VendorUtil
, PageVisibilityService
, $timeout
, $window
, socket
) {
  return {
    restrict: 'E'
  , template: require('./screen.jade')
  , scope: {
      control: '&'
    , device: '&'
    }
  , link: function(scope, element) {
      var URL = window.URL || window.webkitURL
      var BLANK_IMG =
        'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
      var cssTransform = VendorUtil.style(['transform', 'webkitTransform'])

      var device = scope.device()
      var control = scope.control()

      var input = element.find('input')

      var screen = scope.screen = {
        rotation: 0
      , bounds: {
          x: 0
        , y: 0
        , w: 0
        , h: 0
        }
      }

      var scaler = ScalingService.coordinator(
        device.display.width
      , device.display.height
      )

      /**
       * SCREEN HANDLING
       *
       * This section should deal with updating the screen ONLY.
       */
      ;(function() {
        function stop() {
          try {
            ws.onerror = ws.onclose = ws.onmessage = ws.onopen = null
            ws.close()
            ws = null
          }
          catch (err) { /* noop */ }
        }

        var ws = new WebSocket(device.display.url)
        ws.binaryType = 'blob'

        ws.onerror = function errorListener() {
          // @todo Handle
        }

        ws.onclose = function closeListener() {
          // @todo Maybe handle
        }

        ws.onopen = function openListener() {
          checkEnabled()
        }

        var canvas = element.find('canvas')[0]
        var g = canvas.getContext('2d')
        var positioner = element.find('div')[0]

        function vendorBackingStorePixelRatio(g) {
          return g.webkitBackingStorePixelRatio ||
            g.mozBackingStorePixelRatio ||
            g.msBackingStorePixelRatio ||
            g.oBackingStorePixelRatio ||
            g.backingStorePixelRatio || 1
        }

        var devicePixelRatio = window.devicePixelRatio || 1
        var backingStoreRatio = vendorBackingStorePixelRatio(g)
        var frontBackRatio = devicePixelRatio / backingStoreRatio

        var options = {
          autoScaleForRetina: true
        , density: Math.max(1, Math.min(1.5, devicePixelRatio || 1))
        , minscale: 0.36
        }

        var adjustedBoundSize
        var cachedEnabled = false

        function updateBounds() {
          function adjustBoundedSize(w, h) {
            var sw = w * options.density
            var sh = h * options.density
            var f

            if (sw < (f = device.display.width * options.minscale)) {
              sw *= f / sw
              sh *= f / sh
            }

            if (sh < (f = device.display.height * options.minscale)) {
              sw *= f / sw
              sh *= f / sh
            }

            return {
              w: Math.ceil(sw)
            , h: Math.ceil(sh)
            }
          }

          // FIXME: element is an object HTMLUnknownElement in IE9
          var w = screen.bounds.w = element[0].offsetWidth
          var h = screen.bounds.h = element[0].offsetHeight

          // Developer error, let's try to reduce debug time
          if (!w || !h) {
            throw new Error(
              'Unable to read bounds; container must have dimensions'
            )
          }

          var newAdjustedBoundSize = (function() {
            switch (screen.rotation) {
            case 90:
            case 270:
              return adjustBoundedSize(h, w)
            case 0:
            case 180:
              /* falls through */
            default:
              return adjustBoundedSize(w, h)
            }
          })()

          if (!adjustedBoundSize ||
            newAdjustedBoundSize.w !== adjustedBoundSize.w ||
            newAdjustedBoundSize.h !== adjustedBoundSize.h) {
            adjustedBoundSize = newAdjustedBoundSize
            onScreenInterestAreaChanged()
          }
        }

        function shouldUpdateScreen() {
          return (
            // NO if the user has disabled the screen.
            scope.$parent.showScreen &&
            // NO if we're not even using the device anymore.
            device.using &&
            // NO if the page is not visible (e.g. background tab).
            !PageVisibilityService.hidden &&
            // NO if we don't have a connection yet.
            ws.readyState === WebSocket.OPEN
            // YES otherwise
          )
        }

        function checkEnabled() {
          var newEnabled = shouldUpdateScreen()

          if (newEnabled === cachedEnabled) {
            updateBounds()
          }
          else if (newEnabled) {
            updateBounds()
            onScreenInterestGained()
          }
          else {
            g.clearRect(0, 0, canvas.width, canvas.height)
            onScreenInterestLost()
          }

          cachedEnabled = newEnabled
        }

        function onScreenInterestGained() {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send('size ' + adjustedBoundSize.w + 'x' + adjustedBoundSize.h)
            ws.send('on')
          }
        }

        function onScreenInterestAreaChanged() {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send('size ' + adjustedBoundSize.w + 'x' + adjustedBoundSize.h)
          }
        }

        function onScreenInterestLost() {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send('off')
          }
        }

        ws.onmessage = (function() {
          var cachedScreen = {
            rotation: 0
          , bounds: {
              x: 0
            , y: 0
            , w: 0
            , h: 0
            }
          }

          var cachedImageWidth = 0
          var cachedImageHeight = 0
          var cssRotation = 0
          var alwaysUpright = false
          var imagePool = new ImagePool(10)

          function applyQuirks(banner) {
            element[0].classList.toggle(
              'quirk-always-upright', alwaysUpright = banner.quirks.alwaysUpright)
          }

          function hasImageAreaChanged(img) {
            return cachedScreen.bounds.w !== screen.bounds.w ||
              cachedScreen.bounds.h !== screen.bounds.h ||
              cachedImageWidth !== img.width ||
              cachedImageHeight !== img.height ||
              cachedScreen.rotation !== screen.rotation
          }

          function isRotated() {
            return screen.rotation === 90 || screen.rotation === 270
          }

          function updateImageArea(img) {
            if (!hasImageAreaChanged(img)) {
              return
            }

            cachedImageWidth = img.width
            cachedImageHeight = img.height

            if (options.autoScaleForRetina) {
              canvas.width = cachedImageWidth * frontBackRatio
              canvas.height = cachedImageHeight * frontBackRatio
              g.scale(frontBackRatio, frontBackRatio)
            }
            else {
              canvas.width = cachedImageWidth
              canvas.height = cachedImageHeight
            }

            cssRotation += rotator(cachedScreen.rotation, screen.rotation)

            canvas.style[cssTransform] = 'rotate(' + cssRotation + 'deg)'

            cachedScreen.bounds.h = screen.bounds.h
            cachedScreen.bounds.w = screen.bounds.w
            cachedScreen.rotation = screen.rotation

            canvasAspect = canvas.width / canvas.height

            if (isRotated() && !alwaysUpright) {
              canvasAspect = img.height / img.width
              element[0].classList.add('rotated')
            }
            else {
              canvasAspect = img.width / img.height
              element[0].classList.remove('rotated')
            }

            if (alwaysUpright) {
              // If the screen image is always in upright position (but we
              // still want the rotation animation), we need to cancel out
              // the rotation by using another rotation.
              positioner.style[cssTransform] = 'rotate(' + -cssRotation + 'deg)'
            }

            maybeFlipLetterbox()
          }

          return function messageListener(message) {
            screen.rotation = device.display.rotation

            if (message.data instanceof Blob) {
              if (shouldUpdateScreen()) {
                if (scope.displayError) {
                  scope.$apply(function() {
                    scope.displayError = false
                  })
                }

                var blob = new Blob([message.data], {
                  type: 'image/jpeg'
                })

                var img = imagePool.next()

                img.onload = function() {
                  updateImageArea(this)

                  g.drawImage(img, 0, 0, img.width, img.height)

                  // Try to forcefully clean everything to get rid of memory
                  // leaks. Note that despite this effort, Chrome will still
                  // leak huge amounts of memory when the developer tools are
                  // open, probably to save the resources for inspection. When
                  // the developer tools are closed no memory is leaked.
                  img.onload = img.onerror = null
                  img.src = BLANK_IMG
                  img = null
                  blob = null

                  URL.revokeObjectURL(url)
                  url = null
                }

                img.onerror = function() {
                  // Happily ignore. I suppose this shouldn't happen, but
                  // sometimes it does, presumably when we're loading images
                  // too quickly.

                  // Do the same cleanup here as in onload.
                  img.onload = img.onerror = null
                  img.src = BLANK_IMG
                  img = null
                  blob = null

                  URL.revokeObjectURL(url)
                  url = null
                }

                var url = URL.createObjectURL(blob)
                img.src = url
              }
            }
            else if (/^start /.test(message.data)) {
              var banner = {};

              try{
                banner = JSON.parse(message.data.substr('start '.length));
              }catch(err){
                // This shouldn't happen, but if it does, return early
                // to avoid breaking the message queue and log the error
                console.error('Invalid JSON in response', err.stack)
                return;
              }

              var wsId = banner.wsId;
              socket.setWSId(wsId);

              applyQuirks(banner)
            }
            else if (/^nextImgId /.test(message.data)) {
              var nextImgId = message.data.substr('nextImgId '.length);
              imageFile.setNextImgId(nextImgId);
              imageFile.setCurrentDeviceSerial(device.serial)
            }
            else if (message.data === 'secure_on') {
              scope.$apply(function() {
                scope.displayError = 'secure'
              })
            }
          }
        })()

        // NOTE: instead of fa-pane-resize, a fa-child-pane-resize could be better
        scope.$on('fa-pane-resize', _.debounce(updateBounds, 1000))
        scope.$watch('device.using', checkEnabled)
        scope.$on('visibilitychange', checkEnabled)
        scope.$watch('$parent.showScreen', checkEnabled)

        scope.retryLoadingScreen = function() {
          if (scope.displayError === 'secure') {
            control.home()
          }
        }

        scope.$on('guest-portrait', function() {
          control.rotate(0)
        })

        scope.$on('guest-landscape', function() {
          control.rotate(90)
        })

        var canvasAspect = 1
        var parentAspect = 1

        function resizeListener() {
          parentAspect = element[0].offsetWidth / element[0].offsetHeight
          maybeFlipLetterbox()
        }

        function maybeFlipLetterbox() {
          element[0].classList.toggle(
            'letterboxed', parentAspect < canvasAspect)
        }

        $window.addEventListener('beforeunload', stop, false)
        $window.addEventListener('resize', resizeListener, false)
        scope.$on('fa-pane-resize', resizeListener)

        resizeListener()

        scope.$on('$destroy', function() {
          stop()
          $window.removeEventListener('beforeunload', stop, false)
          $window.removeEventListener('resize', resizeListener, false)
        })
      })()

      /**
       * KEYBOARD HANDLING
       *
       * This should be moved elsewhere, but due to shared dependencies and
       * elements it's currently here. So basically due to laziness.
       *
       * For now, try to keep the whole section as a separate unit as much
       * as possible.
       */
      ;(function() {
        function isChangeCharsetKey(e) {
          // Add any special key here for changing charset
          //console.log('e', e)

          // Chrome/Safari/Opera
          if (
            // Mac | Kinesis keyboard | Karabiner | Latin key, Kana key
          e.keyCode === 0 && e.keyIdentifier === 'U+0010' ||

            // Mac | MacBook Pro keyboard | Latin key, Kana key
          e.keyCode === 0 && e.keyIdentifier === 'U+0020' ||

            // Win | Lenovo X230 keyboard | Alt+Latin key
          e.keyCode === 246 && e.keyIdentifier === 'U+00F6' ||

            // Win | Lenovo X230 keyboard | Convert key
          e.keyCode === 28 && e.keyIdentifier === 'U+001C'
          ) {
            return true
          }

          // Firefox
          switch (e.key) {
            case 'Convert': // Windows | Convert key
            case 'Alphanumeric': // Mac | Latin key
            case 'RomanCharacters': // Windows/Mac | Latin key
            case 'KanjiMode': // Windows/Mac | Kana key
              return true
          }

          return false
        }

        function handleSpecialKeys(e) {
          if (isChangeCharsetKey(e)) {
            e.preventDefault()
            control.keyPress('switch_charset')
            return true
          }

          return false
        }

        function keydownListener(e) {
          // Prevent tab from switching focus to the next element, we only want
          // that to happen on the device side.
          if (e.keyCode === 9) {
            e.preventDefault()
          }
          control.keyDown(e.keyCode)
        }

        function keyupListener(e) {
          if (!handleSpecialKeys(e)) {
            control.keyUp(e.keyCode)
          }
        }

        function pasteListener(e) {
          // Prevent value change or the input event sees it. This way we get
          // the real value instead of any "\n" -> " " conversions we might see
          // in the input value.
          e.preventDefault()
          control.paste(e.clipboardData.getData('text/plain'))
        }

        function copyListener(e) {
          e.preventDefault()
          // This is asynchronous and by the time it returns we will no longer
          // have access to setData(). In other words it doesn't work. Currently
          // what happens is that on the first copy, it will attempt to fetch
          // the clipboard contents. Only on the second copy will it actually
          // copy that to the clipboard.
          control.getClipboardContent()
          if (control.clipboardContent) {
            e.clipboardData.setData('text/plain', control.clipboardContent)
          }
        }

        function inputListener() {
          // Why use the input event if we don't let it handle pasting? The
          // reason is that on latest Safari (Version 8.0 (10600.1.25)), if
          // you use the "Romaji" Kotoeri input method, we'll never get any
          // keypress events. It also causes us to lose the very first keypress
          // on the page. Currently I'm not sure if we can fix that one.
          control.type(this.value)
          this.value = ''
        }

        input.bind('keydown', keydownListener)
        input.bind('keyup', keyupListener)
        input.bind('input', inputListener)
        input.bind('paste', pasteListener)
        input.bind('copy', copyListener)
      })()

      /**
       * TOUCH HANDLING
       *
       * This should be moved elsewhere, but due to shared dependencies and
       * elements it's currently here. So basically due to laziness.
       *
       * For now, try to keep the whole section as a separate unit as much
       * as possible.
       */
      ;(function() {
        var slots = []
        var slotted = Object.create(null)
        var fingers = []
        var seq = -1
        var cycle = 100
        var fakePinch = false
        var lastPossiblyBuggyMouseUpEvent = 0

        function nextSeq() {
          return ++seq >= cycle ? (seq = 0) : seq
        }

        function createSlots() {
          // The reverse order is important because slots and fingers are in
          // opposite sort order. Anyway don't change anything here unless
          // you understand what it does and why.
          for (var i = 9; i >= 0; --i) {
            var finger = createFinger(i)
            element.append(finger)
            slots.push(i)
            fingers.unshift(finger)
          }
        }

        function activateFinger(index, x, y, pressure) {
          var scale = 0.5 + pressure
          fingers[index].classList.add('active')
          fingers[index].style[cssTransform] =
            'translate3d(' + x + 'px,' + y + 'px,0) ' +
            'scale(' + scale + ',' + scale + ')'
        }

        function deactivateFinger(index) {
          fingers[index].classList.remove('active')
        }

        function deactivateFingers() {
          for (var i = 0, l = fingers.length; i < l; ++i) {
            fingers[i].classList.remove('active')
          }
        }

        function createFinger(index) {
          var el = document.createElement('span')
          el.className = 'finger finger-' + index
          return el
        }

        function calculateBounds() {
          var el = element[0]

          screen.bounds.w = el.offsetWidth
          screen.bounds.h = el.offsetHeight
          screen.bounds.x = 0
          screen.bounds.y = 0

          while (el.offsetParent) {
            screen.bounds.x += el.offsetLeft
            screen.bounds.y += el.offsetTop
            el = el.offsetParent
          }
        }

        function mouseDownListener(event) {
          var e = event
          if (e.originalEvent) {
            e = e.originalEvent
          }

          // Skip secondary click
          if (e.which === 3) {
            return
          }

          e.preventDefault()

          fakePinch = e.altKey

          calculateBounds()
          startMousing()

          var x = e.pageX - screen.bounds.x
          var y = e.pageY - screen.bounds.y
          var pressure = 0.5
          var scaled = scaler.coords(
                screen.bounds.w
              , screen.bounds.h
              , x
              , y
              , screen.rotation
              )

          control.touchDown(nextSeq(), 0, scaled.xP, scaled.yP, pressure)

          if (fakePinch) {
            control.touchDown(nextSeq(), 1, 1 - scaled.xP, 1 - scaled.yP,
              pressure)
          }

          control.touchCommit(nextSeq())

          activateFinger(0, x, y, pressure)

          if (fakePinch) {
            activateFinger(1, -e.pageX + screen.bounds.x + screen.bounds.w,
              -e.pageY + screen.bounds.y + screen.bounds.h, pressure)
          }

          element.bind('mousemove', mouseMoveListener)
          $document.bind('mouseup', mouseUpListener)
          $document.bind('mouseleave', mouseUpListener)

          if (lastPossiblyBuggyMouseUpEvent &&
              lastPossiblyBuggyMouseUpEvent.timeStamp > e.timeStamp) {
            // We got mouseup before mousedown. See mouseUpBugWorkaroundListener
            // for details.
            mouseUpListener(lastPossiblyBuggyMouseUpEvent)
          }
          else {
            lastPossiblyBuggyMouseUpEvent = null
          }
        }

        function mouseMoveListener(event) {
          var e = event
          if (e.originalEvent) {
            e = e.originalEvent
          }

          // Skip secondary click
          if (e.which === 3) {
            return
          }
          e.preventDefault()

          var addGhostFinger = !fakePinch && e.altKey
          var deleteGhostFinger = fakePinch && !e.altKey

          fakePinch = e.altKey

          var x = e.pageX - screen.bounds.x
          var y = e.pageY - screen.bounds.y
          var pressure = 0.5
          var scaled = scaler.coords(
                screen.bounds.w
              , screen.bounds.h
              , x
              , y
              , screen.rotation
              )

          control.touchMove(nextSeq(), 0, scaled.xP, scaled.yP, pressure)

          if (addGhostFinger) {
            control.touchDown(nextSeq(), 1, 1 - scaled.xP, 1 - scaled.yP, pressure)
          }
          else if (deleteGhostFinger) {
            control.touchUp(nextSeq(), 1)
          }
          else if (fakePinch) {
            control.touchMove(nextSeq(), 1, 1 - scaled.xP, 1 - scaled.yP, pressure)
          }

          control.touchCommit(nextSeq())

          activateFinger(0, x, y, pressure)

          if (deleteGhostFinger) {
            deactivateFinger(1)
          }
          else if (fakePinch) {
            activateFinger(1, -e.pageX + screen.bounds.x + screen.bounds.w,
              -e.pageY + screen.bounds.y + screen.bounds.h, pressure)
          }
        }

        function mouseUpListener(event) {
          var e = event
          if (e.originalEvent) {
            e = e.originalEvent
          }

          // Skip secondary click
          if (e.which === 3) {
            return
          }
          e.preventDefault()

          control.touchUp(nextSeq(), 0)

          if (fakePinch) {
            control.touchUp(nextSeq(), 1)
          }

          control.touchCommit(nextSeq())

          deactivateFinger(0)

          if (fakePinch) {
            deactivateFinger(1)
          }

          stopMousing()
        }

        /**
         * Do NOT remove under any circumstances. Currently, in the latest
         * Safari (Version 8.0 (10600.1.25)), if an input field is focused
         * while we do a tap click on an MBP trackpad ("Tap to click" in
         * Settings), it sometimes causes the mouseup event to trigger before
         * the mousedown event (but event.timeStamp will be correct). It
         * doesn't happen in any other browser. The following minimal test
         * case triggers the same behavior (although less frequently). Keep
         * tapping and you'll eventually see see two mouseups in a row with
         * the same counter value followed by a mousedown with a new counter
         * value. Also, when the bug happens, the cursor in the input field
         * stops blinking. It may take up to 300 attempts to spot the bug on
         * a MacBook Pro (Retina, 15-inch, Mid 2014).
         *
         *     <!doctype html>
         *
         *     <div id="touchable"
         *       style="width: 100px; height: 100px; background: green"></div>
         *     <input id="focusable" type="text" />
         *
         *     <script>
         *     var touchable = document.getElementById('touchable')
         *       , focusable = document.getElementById('focusable')
         *       , counter = 0
         *
         *     function mousedownListener(e) {
         *       counter += 1
         *       console.log('mousedown', counter, e, e.timeStamp)
         *       e.preventDefault()
         *     }
         *
         *     function mouseupListener(e) {
         *       e.preventDefault()
         *       console.log('mouseup', counter, e, e.timeStamp)
         *       focusable.focus()
         *     }
         *
         *     touchable.addEventListener('mousedown', mousedownListener, false)
         *     touchable.addEventListener('mouseup', mouseupListener, false)
         *     </script>
         *
         * I believe that the bug is caused by some kind of a race condition
         * in Safari. Using a textarea or a focused contenteditable does not
         * get rid of the bug. The bug also happens if the text field is
         * focused manually by the user (not with .focus()).
         *
         * It also doesn't help if you .blur() before .focus().
         *
         * So basically we'll just have to store the event on mouseup and check
         * if we should do the browser's job in the mousedown handler.
         */
        function mouseUpBugWorkaroundListener(e) {
          lastPossiblyBuggyMouseUpEvent = e
        }

        function startMousing() {
          control.gestureStart(nextSeq())
          input[0].focus()
        }

        function stopMousing() {
          element.unbind('mousemove', mouseMoveListener)
          $document.unbind('mouseup', mouseUpListener)
          $document.unbind('mouseleave', mouseUpListener)
          deactivateFingers()
          control.gestureStop(nextSeq())
        }

        function touchStartListener(event) {
          var e = event
          e.preventDefault()

          //Make it jQuery compatible also
          if (e.originalEvent) {
            e = e.originalEvent
          }

          calculateBounds()

          if (e.touches.length === e.changedTouches.length) {
            startTouching()
          }

          var currentTouches = Object.create(null)
          var i, l

          for (i = 0, l = e.touches.length; i < l; ++i) {
            currentTouches[e.touches[i].identifier] = 1
          }

          function maybeLostTouchEnd(id) {
            return !(id in currentTouches)
          }

          // We might have lost a touchend event due to various edge cases
          // (literally) such as dragging from the bottom of the screen so that
          // the control center appears. If so, let's ask for a reset.
          if (Object.keys(slotted).some(maybeLostTouchEnd)) {
            Object.keys(slotted).forEach(function(id) {
              slots.push(slotted[id])
              delete slotted[id]
            })
            slots.sort().reverse()
            control.touchReset(nextSeq())
            deactivateFingers()
          }

          if (!slots.length) {
            // This should never happen but who knows...
            throw new Error('Ran out of multitouch slots')
          }

          for (i = 0, l = e.changedTouches.length; i < l; ++i) {
            var touch = e.changedTouches[i]
            var slot = slots.pop()
            var x = touch.pageX - screen.bounds.x
            var y = touch.pageY - screen.bounds.y
            var pressure = touch.force || 0.5
            var scaled = scaler.coords(
                  screen.bounds.w
                , screen.bounds.h
                , x
                , y
                , screen.rotation
                )

            slotted[touch.identifier] = slot
            control.touchDown(nextSeq(), slot, scaled.xP, scaled.yP, pressure)
            activateFinger(slot, x, y, pressure)
          }

          element.bind('touchmove', touchMoveListener)
          $document.bind('touchend', touchEndListener)
          $document.bind('touchleave', touchEndListener)

          control.touchCommit(nextSeq())
        }

        function touchMoveListener(event) {
          var e = event
          e.preventDefault()

          if (e.originalEvent) {
            e = e.originalEvent
          }

          for (var i = 0, l = e.changedTouches.length; i < l; ++i) {
            var touch = e.changedTouches[i]
            var slot = slotted[touch.identifier]
            var x = touch.pageX - screen.bounds.x
            var y = touch.pageY - screen.bounds.y
            var pressure = touch.force || 0.5
            var scaled = scaler.coords(
                  screen.bounds.w
                , screen.bounds.h
                , x
                , y
                , screen.rotation
                )

            control.touchMove(nextSeq(), slot, scaled.xP, scaled.yP, pressure)
            activateFinger(slot, x, y, pressure)
          }

          control.touchCommit(nextSeq())
        }

        function touchEndListener(event) {
          var e = event
          if (e.originalEvent) {
            e = e.originalEvent
          }

          var foundAny = false

          for (var i = 0, l = e.changedTouches.length; i < l; ++i) {
            var touch = e.changedTouches[i]
            var slot = slotted[touch.identifier]
            if (typeof slot === 'undefined') {
              // We've already disposed of the contact. We may have gotten a
              // touchend event for the same contact twice.
              continue
            }
            delete slotted[touch.identifier]
            slots.push(slot)
            control.touchUp(nextSeq(), slot)
            deactivateFinger(slot)
            foundAny = true
          }

          if (foundAny) {
            control.touchCommit(nextSeq())
            if (!e.touches.length) {
              stopTouching()
            }
          }
        }

        function startTouching() {
          control.gestureStart(nextSeq())
        }

        function stopTouching() {
          element.unbind('touchmove', touchMoveListener)
          $document.unbind('touchend', touchEndListener)
          $document.unbind('touchleave', touchEndListener)
          deactivateFingers()
          control.gestureStop(nextSeq())
        }

        element.on('touchstart', touchStartListener)
        element.on('mousedown', mouseDownListener)
        element.on('mouseup', mouseUpBugWorkaroundListener)

        createSlots()
      })()
    }
  }
}
