/*

Siesta 5.3.2
Copyright(c) 2009-2020 Bryntum AB
https://bryntum.com/contact
https://bryntum.com/products/siesta/license

*/
/**
 @class Siesta.Recorder.Role.CanRecordWheel

 A mixin, providing the feature of recording the "wheel" event.

 */
Role('Siesta.Recorder.Role.CanRecordWheel', {

    has : {
        /**
         * @cfg {Boolean} recordWheel Set this option to `true` to enable recording of `wheel` events.
         * Several consequent `wheel` events on the same element will be merged into one `wheel` action.
         */
        recordWheel : true,

        /**
         * @cfg {Number} wheelEventBuffer If similar wheel events are fired on same target during this time (ms),
         * (and in same direction / axis) merge the events
         */
        wheelEventBuffer    : 200,

        skipIfNoModifierKeysPressed : false
    },

    override : {

        initialize : function () {
            var me = this;

            me.SUPERARG(arguments);

            me.onWheelEvent = me.onWheelEvent.bind(me);
        },


        onStart : function () {
            this.SUPERARG(arguments);

            var win = this.window;
            var doc = win.document;

            // Observe wheel events
            if (this.recordWheel) {
                doc.addEventListener('wheel', this.onWheelEvent, true);
            }
        },


        onStop : function () {
            this.SUPERARG(arguments);

            var win = this.window;
            var doc = win.document;

            if (this.recordWheel) {
                doc.removeEventListener('wheel', this.onWheelEvent, true);
            }
        },

        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
        sign : Math.sign || function(x) {
            // If x is NaN, the result is NaN.
            // If x is -0, the result is -0.
            // If x is +0, the result is +0.
            // If x is negative and not -0, the result is -1.
            // If x is positive and not +0, the result is +1.
            return ((x > 0) - (x < 0)) || +x;
        },

        isSameWheelAxisAndDirection : function(event1, event2) {
            return this.sign(event1.deltaX) === this.sign(event2.deltaX) &&
                this.sign(event1.deltaY) === this.sign(event2.deltaY) &&
                this.sign(event1.deltaZ) === this.sign(event2.deltaZ);
        },

        onWheelEvent : function (wheelEvent) {
            var me         = this;
            var lastAction = this.getLastAction();

            if (me.skipIfNoModifierKeysPressed && !wheelEvent.ctrlKey && !wheelEvent.altKey && !wheelEvent.metaKey && !wheelEvent.shiftKey) {
                return;
            }

            // Merge subsequent wheel events (they occur at very high rates on a touch pad) which go in the same axis/direction
            if (lastAction && lastAction.action === 'wheel' && wheelEvent.target === lastAction.sourceEvent.target) {
                var lastEvent = lastAction.sourceEvent;

                if (me.isSameWheelAxisAndDirection(wheelEvent, lastEvent.rawEvent) && Date.now() - lastAction.timestamp < me.wheelEventBuffer) {
                    lastAction.options.deltaX += wheelEvent.deltaX;
                    lastAction.options.deltaY += wheelEvent.deltaY;
                    lastAction.options.deltaZ += wheelEvent.deltaZ;

                    this.fireEvent('actionupdate', lastAction);

                    return;
                }
            }

            me.onDomEvent(wheelEvent);
        }
    }
});