    /*

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

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

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

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

        has : {
            /**
             * @cfg {Boolean} recordScroll Set this option to `true` to enable recording of `scroll` events.
             * This even occurs, when some element on the page, or the page itself, is scrolled by user.
             * Several consequent `scroll` events on the same element will be merged into one `scrollTo` action.
             *
             * Note, that when replaying scripts, recorded with this option enabled, you might want to disable
             * the {@link Siesta.Project.Browser#autoScrollElementsIntoView autoScrollElementsIntoView} option,
             * as it will be interfering with the recorded actions.
             */
            recordScroll        : false
        },

        override : {

            initialize : function () {
                var me = this;

                me.SUPERARG(arguments);

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

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

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

                // Observe scroll events
                if (this.recordScroll) {
                    doc.addEventListener('scroll', this.onScrollEvent, true);
                }
            },

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

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

                if (this.recordScroll) {
                    doc.removeEventListener('scroll', this.onScrollEvent, true);
                }
            },

            onScrollEvent : function (scrollEvent) {
                var me      = this;
                var target  = scrollEvent.target;

                var win     = me.window
                var doc     = win.document

                var lastAction  = this.getLastAction()

                // note that "target" here is unchanged and can be a document
                if (lastAction && lastAction.action == 'scrollTo' && target == lastAction.sourceEvent.target) {
                    // repeated scroll on the same target
                    if (target === doc) target = this.getElForPageScroll(win);

                    lastAction.value    = [ target.scrollLeft, target.scrollTop ]

                    this.fireEvent('actionupdate', lastAction)
                } else {
                    var isPageScroll;
                    // scroll on the new target

                    // page scroll events are fired with document as target, switch it to use body element
                    if (target === doc) {
                        isPageScroll = true;
                        target       = this.getElForPageScroll(win);
                    }

                    var cursorPosition  = this.cursorPosition

                    // For page scroll we have no way of knowing if it was triggered by direct scrolling or side effect
                    // So always record it
                    if (cursorPosition.length === 2 && !isPageScroll) {
                        var viewportX       = this.pageXtoViewportX(cursorPosition[ 0 ], win)
                        var viewportY       = this.pageYtoViewportY(cursorPosition[ 1 ], win)

                        // Ignore scroll if cursor is outside of scroll target
                        // we consider such scrolls as happened because of side-effect of some other user action
                        if (!this.isPointWithinElement(viewportX, viewportY, target)) return
                    }

                    this.addAction({
                        action          : 'scrollTo',

                        target          : this.getPossibleTargets(scrollEvent, false, target),
                        value           : [ target.scrollLeft, target.scrollTop ],

                        sourceEvent     : Siesta.Recorder.Event.fromDomEvent(scrollEvent)
                    })
                }
            }
        }
    });