/**
 * A event recognizer which knows when you tap and hold for more than 1 second.
 */
Ext.define('Ext.event.gesture.LongPress', {
    extend: 'Ext.event.gesture.SingleTouch',

    priority: 400,

    inheritableStatics: {
        /**
         * @private
         * @static
         * @inheritable
         */
        DURATION_NOT_ENOUGH: 'Duration Not Enough'
    },

    config: {
        moveDistance: 8,
        minDuration: 1000
    },

    handledEvents: ['longpress', 'taphold'],

    /**
     * @member Ext.dom.Element
     * @event longpress
     * Fires when you touch and hold still for more than 1 second.
     * @param {Ext.event.Event} event The {@link Ext.event.Event} event encapsulating the DOM event.
     * @param {HTMLElement} node The target of the event.
     * @param {Object} options The options object passed to Ext.mixin.Observable.addListener.
     */

    /**
     * @member Ext.dom.Element
     * @event taphold
     * @inheritdoc Ext.dom.Element#longpress
     */

    fireLongPress: function(e) {
        this.fire('longpress', e, {
            touch: e.changedTouches[0],
            duration: this.getMinDuration()
        });

        this.isLongPress = true;
    },

    onTouchStart: function(e) {
        if (this.callParent(arguments) === false) {
            return false;
        }
        this.startPoint = e.changedTouches[0].point;

        this.isLongPress = false;

        this.setLongPressTimer(e);
    },

    setLongPressTimer: function(e) {
        var me = this;

        me.timer = Ext.defer(function() {
            me.fireLongPress(e);
        }, me.getMinDuration());
    },

    onTouchMove: function(e) {
        var point = e.changedTouches[0].point;
        if (Math.abs(point.getDistanceTo(this.startPoint)) >= this.getMoveDistance()) {
            return this.fail(this.self.TOUCH_MOVED);
        }
    },

    onTouchEnd: function() {
        if (!this.isLongPress) {
            return this.fail(this.self.DURATION_NOT_ENOUGH);
        }
    },

    fail: function() {
        clearTimeout(this.timer);

        return this.callParent(arguments);
    },

    reset: function() {
        this.isLongPress = this.startPoint = null;
    },

    fire: function(eventName) {
        if (eventName === 'longpress') {
            var args = Array.prototype.slice.call(arguments);
            args[0] = 'taphold';

            this.fire.apply(this, args);
        }

        return this.callParent(arguments);
    }
}, function(LongPress) {
    var gestures = Ext.manifest.gestures;
    LongPress.instance = new LongPress(gestures && gestures.longPress);
});
