Show:
/* Copyright © 2015-2016 David Valdman */

define(function(require, exports, module){
    var EventHandler = require('../events/EventHandler');
    var TwoFingerInput = require('./_TwoFingerInput');
    var OptionsManager = require('../core/_OptionsManager');

    /**
     * Detects two-finger pinching motion and emits `start`, `update` and
     *  `end` events with the payload data:
     *
     *      `value`         - Distance between the two touches
     *      `delta`         - Differential in successive distances
     *      `velocity`      - Relative velocity between two touches
     *      `displacement`  - Total accumulated displacement
     *      `center`        - Midpoint between the two touches
     *
     * @example
     *
     *      var pinchInput = new PinchInput();
     *
     *      pinchInput.subscribe(Engine) // listens on `window` events
     *
     *      pinchInput.on('start', function(payload){
     *          console.log('start', payload);
     *      });
     *
     *      pinchInput.on('update', function(payload){
     *          console.log('update', payload);
     *      });
     *
     *      pinchInput.on('end', function(payload){
     *          console.log('end', payload);
     *      });
     *
     * @class PinchInput
     * @extends Inputs._TwoFingerInput
     * @uses Core._OptionsManager
     * @constructor
     * @param options {Object}                  Options
     * @param [options.scale=1] {Number}        Scale the response to pinch
     * @param [options.direction] {Number}      Direction to project movement onto.
     *                                          Options found in TouchInput.DIRECTION.
     * @param [options.rails=false] {Boolean}   If a direction is specified, movement in the
     *                                          orthogonal direction is suppressed
     */
    function PinchInput(options){
        this.options = OptionsManager.setOptions(this, options);

        this._eventInput = new TwoFingerInput(this.options);
        this._eventOutput = new EventHandler();

        EventHandler.setInputHandler(this, this._eventInput);
        EventHandler.setOutputHandler(this, this._eventOutput);
        
        this._eventInput.on('twoFingerStart', start.bind(this));
        this._eventInput.on('twoFingerUpdate', update.bind(this));
        this._eventInput.on('twoFingerEnd', end.bind(this));

        this.payload = {
            delta : null,
            velocity : null,
            value : null,
            center : []
        };

        this.value = 0;
        this.direction = [];
    }

    PinchInput.prototype = Object.create(TwoFingerInput.prototype);
    PinchInput.prototype.constructor = PinchInput;

    PinchInput.DIRECTION = {
        X : 0,
        Y : 1
    };

    PinchInput.DEFAULT_OPTIONS = {
        scale : 1,
        direction : undefined,
        rails : true
    };

    function start(data){
        var center = TwoFingerInput.calculateCenter.call(this, data[0].position, data[1].position);
        var distance = TwoFingerInput.calculateDistance.call(this, data[0].position, data[1].position);
        this.direction = TwoFingerInput.calculateOrientation.call(this, data[0].position, data[1].position);

        var payload = this.payload;
        payload.value = distance;
        payload.center = center;

        this._eventOutput.emit('start', payload);

        this.value = distance;
    }

    function update(data){
        var center = TwoFingerInput.calculateCenter.call(this, data[0].position, data[1].position);
        var distance = TwoFingerInput.calculateDistance.call(this, data[0].position, data[1].position);
        var velocity = TwoFingerInput.calculateVelocity.call(this, data[0].velocity, data[1].velocity);
        var currDirection = TwoFingerInput.calculateOrientation.call(this, data[0].position, data[1].position);

        var changedDirection = TwoFingerInput.detectOrientationChange.call(this, currDirection, this.direction);
        var scale = this.options.scale;
        var delta;

        if (this.options.direction === undefined){
            if (changedDirection){
                distance[0] *= -1;
                distance[1] *= -1;
            }

            delta = [
                scale * (distance[0] - this.value[0]),
                scale * (distance[1] - this.value[1])
            ];
        }
        else {
            if (changedDirection) distance *= -1;
            delta = scale * (distance - this.value);
        }

        var payload = this.payload;
        payload.delta = delta;
        payload.velocity = velocity;
        payload.value = this.value;
        payload.center = center;

        this._eventOutput.emit('update', payload);

        this.value = distance;
    }

    function end(){
        this._eventOutput.emit('end', this.payload);
    }

    module.exports = PinchInput;
});