/**
 * DevExtreme (cjs/events/gesture/emitter.gesture.scroll.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
exports.default = void 0;
var _events_engine = _interopRequireDefault(require("../../events/core/events_engine"));
var _class = _interopRequireDefault(require("../../core/class"));
var _index = require("../../events/utils/index");
var _emitter = _interopRequireDefault(require("../../events/gesture/emitter.gesture"));
var _emitter_registrator = _interopRequireDefault(require("../../events/core/emitter_registrator"));
var _frame = require("../../animation/frame");
var _devices = _interopRequireDefault(require("../../core/devices"));

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}
const abstract = _class.default.abstract;
const realDevice = _devices.default.real();
const SCROLL_EVENT = "scroll";
const SCROLL_INIT_EVENT = "dxscrollinit";
const SCROLL_START_EVENT = "dxscrollstart";
const SCROLL_MOVE_EVENT = "dxscroll";
const SCROLL_END_EVENT = "dxscrollend";
const SCROLL_STOP_EVENT = "dxscrollstop";
const SCROLL_CANCEL_EVENT = "dxscrollcancel";
const Locker = _class.default.inherit(function() {
    const NAMESPACED_SCROLL_EVENT = (0, _index.addNamespace)("scroll", "dxScrollEmitter");
    return {
        ctor: function(element) {
            this._element = element;
            this._locked = false;
            this._proxiedScroll = e => {
                if (!this._disposed) {
                    this._scroll(e)
                }
            };
            _events_engine.default.on(this._element, NAMESPACED_SCROLL_EVENT, this._proxiedScroll)
        },
        _scroll: abstract,
        check: function(e, callback) {
            if (this._locked) {
                callback()
            }
        },
        dispose: function() {
            this._disposed = true;
            _events_engine.default.off(this._element, NAMESPACED_SCROLL_EVENT, this._proxiedScroll)
        }
    }
}());
const TimeoutLocker = Locker.inherit({
    ctor: function(element, timeout) {
        this.callBase(element);
        this._timeout = timeout
    },
    _scroll: function() {
        this._prepare();
        this._forget()
    },
    _prepare: function() {
        if (this._timer) {
            this._clearTimer()
        }
        this._locked = true
    },
    _clearTimer: function() {
        clearTimeout(this._timer);
        this._locked = false;
        this._timer = null
    },
    _forget: function() {
        const that = this;
        this._timer = setTimeout((function() {
            that._clearTimer()
        }), this._timeout)
    },
    dispose: function() {
        this.callBase();
        this._clearTimer()
    }
});
const WheelLocker = TimeoutLocker.inherit({
    ctor: function(element) {
        this.callBase(element, 400);
        this._lastWheelDirection = null
    },
    check: function(e, callback) {
        this._checkDirectionChanged(e);
        this.callBase(e, callback)
    },
    _checkDirectionChanged: function(e) {
        if (!(0, _index.isDxMouseWheelEvent)(e)) {
            this._lastWheelDirection = null;
            return
        }
        const direction = e.shiftKey || false;
        const directionChange = null !== this._lastWheelDirection && direction !== this._lastWheelDirection;
        this._lastWheelDirection = direction;
        this._locked = this._locked && !directionChange
    }
});
let PointerLocker = TimeoutLocker.inherit({
    ctor: function(element) {
        this.callBase(element, 400)
    }
});
! function() {
    const {
        ios: isIos,
        android: isAndroid
    } = realDevice;
    if (!(isIos || isAndroid)) {
        return
    }
    PointerLocker = Locker.inherit({
        _scroll: function() {
            this._locked = true;
            const that = this;
            (0, _frame.cancelAnimationFrame)(this._scrollFrame);
            this._scrollFrame = (0, _frame.requestAnimationFrame)((function() {
                that._locked = false
            }))
        },
        check: function(e, callback) {
            (0, _frame.cancelAnimationFrame)(this._scrollFrame);
            (0, _frame.cancelAnimationFrame)(this._checkFrame);
            const that = this;
            const callBase = this.callBase;
            this._checkFrame = (0, _frame.requestAnimationFrame)((function() {
                callBase.call(that, e, callback);
                that._locked = false
            }))
        },
        dispose: function() {
            this.callBase();
            (0, _frame.cancelAnimationFrame)(this._scrollFrame);
            (0, _frame.cancelAnimationFrame)(this._checkFrame)
        }
    })
}();
const ScrollEmitter = _emitter.default.inherit(function() {
    const FRAME_DURATION = Math.round(1e3 / 60);
    return {
        ctor: function(element) {
            this.callBase.apply(this, arguments);
            this.direction = "both";
            this._pointerLocker = new PointerLocker(element);
            this._wheelLocker = new WheelLocker(element)
        },
        validate: function() {
            return true
        },
        configure: function(data) {
            if (data.scrollTarget) {
                this._pointerLocker.dispose();
                this._wheelLocker.dispose();
                this._pointerLocker = new PointerLocker(data.scrollTarget);
                this._wheelLocker = new WheelLocker(data.scrollTarget)
            }
            this.callBase(data)
        },
        _init: function(e) {
            this._wheelLocker.check(e, function() {
                if ((0, _index.isDxMouseWheelEvent)(e)) {
                    this._accept(e)
                }
            }.bind(this));
            this._pointerLocker.check(e, function() {
                const skipCheck = this.isNative && (0, _index.isMouseEvent)(e);
                if (!(0, _index.isDxMouseWheelEvent)(e) && !skipCheck) {
                    this._accept(e)
                }
            }.bind(this));
            this._fireEvent("dxscrollinit", e);
            this._prevEventData = (0, _index.eventData)(e)
        },
        move: function(e) {
            this.callBase.apply(this, arguments);
            e.isScrollingEvent = this.isNative || e.isScrollingEvent
        },
        _start: function(e) {
            this._savedEventData = (0, _index.eventData)(e);
            this._fireEvent("dxscrollstart", e);
            this._prevEventData = (0, _index.eventData)(e)
        },
        _move: function(e) {
            const currentEventData = (0, _index.eventData)(e);
            this._fireEvent("dxscroll", e, {
                delta: (0, _index.eventDelta)(this._prevEventData, currentEventData)
            });
            const delta = (0, _index.eventDelta)(this._savedEventData, currentEventData);
            if (delta.time > 200) {
                this._savedEventData = this._prevEventData
            }
            this._prevEventData = (0, _index.eventData)(e)
        },
        _end: function(e) {
            const endEventDelta = (0, _index.eventDelta)(this._prevEventData, (0, _index.eventData)(e));
            let velocity = {
                x: 0,
                y: 0
            };
            if (!(0, _index.isDxMouseWheelEvent)(e) && endEventDelta.time < 100) {
                const delta = (0, _index.eventDelta)(this._savedEventData, this._prevEventData);
                const velocityMultiplier = FRAME_DURATION / delta.time;
                velocity = {
                    x: delta.x * velocityMultiplier,
                    y: delta.y * velocityMultiplier
                }
            }
            this._fireEvent("dxscrollend", e, {
                velocity: velocity
            })
        },
        _stop: function(e) {
            this._fireEvent("dxscrollstop", e)
        },
        cancel: function(e) {
            this.callBase.apply(this, arguments);
            this._fireEvent("dxscrollcancel", e)
        },
        dispose: function() {
            this.callBase.apply(this, arguments);
            this._pointerLocker.dispose();
            this._wheelLocker.dispose()
        },
        _clearSelection: function() {
            if (this.isNative) {
                return
            }
            return this.callBase.apply(this, arguments)
        },
        _toggleGestureCover: function() {
            if (this.isNative) {
                return
            }
            return this.callBase.apply(this, arguments)
        }
    }
}());
(0, _emitter_registrator.default)({
    emitter: ScrollEmitter,
    events: ["dxscrollinit", "dxscrollstart", "dxscroll", "dxscrollend", "dxscrollstop", "dxscrollcancel"]
});
var _default = {
    init: "dxscrollinit",
    start: "dxscrollstart",
    move: "dxscroll",
    end: "dxscrollend",
    stop: "dxscrollstop",
    cancel: "dxscrollcancel",
    scroll: "scroll"
};
exports.default = _default;
module.exports = exports.default;
module.exports.default = exports.default;
