"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SeekBarHandler = void 0;
var nodeeventsubscriber_1 = require("./nodeeventsubscriber");
var types_1 = require("./types");
var navigationalgorithm_1 = require("./navigationalgorithm");
var DefaultScrubSpeedPercentage = 0.005;
var ScrubSpeedClearInterval = 100;
var ScrubSpeedMultiplier = 1.1;
/**
 * Handles Spatial Navigation interaction with the seek bar. Ensures, that seek operations can be executed and that the
 * scrubbing tooltip is shown as if the user scrubbed using the mouse/touchscreen.
 */
var SeekBarHandler = /** @class */ (function () {
    function SeekBarHandler(rootNavigationGroup) {
        var _this = this;
        this.rootNavigationGroup = rootNavigationGroup;
        this.cursorPosition = { x: 0, y: 0 };
        this.isScrubbing = false;
        this.scrubSpeedPercentage = DefaultScrubSpeedPercentage;
        this.onNavigation = function (direction, target, preventDefault) {
            if (!isSeekBarWrapper(target)) {
                return;
            }
            if (direction === types_1.Direction.UP || direction === types_1.Direction.DOWN) {
                _this.stopSeeking(getSeekBar(target));
                return;
            }
            _this.initializeOrUpdateCursorPosition(target, direction);
            _this.dispatchMouseMoveEvent(getSeekBar(target));
            preventDefault();
        };
        this.onAction = function (action, target, preventDefault) {
            if (!isSeekBarWrapper(target)) {
                return;
            }
            var seekBar = getSeekBar(target);
            if (action === types_1.Action.SELECT && _this.isScrubbing) {
                _this.dispatchMouseClickEvent(seekBar);
                preventDefault();
            }
            else if (action === types_1.Action.BACK) {
                _this.stopSeeking(seekBar);
                preventDefault();
            }
        };
        this.rootNavigationGroup.onAction = this.onAction;
        this.eventSubscriber = new nodeeventsubscriber_1.NodeEventSubscriber();
        this.rootNavigationGroup.onNavigation = this.onNavigation;
    }
    SeekBarHandler.prototype.updateScrubSpeedPercentage = function () {
        var _this = this;
        clearTimeout(this.scrubSpeedResetTimeout);
        this.scrubSpeedPercentage *= ScrubSpeedMultiplier;
        this.scrubSpeedResetTimeout = window.setTimeout(function () { return _this.scrubSpeedPercentage = DefaultScrubSpeedPercentage; }, ScrubSpeedClearInterval);
    };
    SeekBarHandler.prototype.getIncrement = function (direction, seekBarWrapper) {
        this.updateScrubSpeedPercentage();
        var seekBarWidth = seekBarWrapper.getBoundingClientRect().width;
        var increment = seekBarWidth * this.scrubSpeedPercentage;
        return direction === types_1.Direction.RIGHT ? increment : -increment;
    };
    SeekBarHandler.prototype.resetCursorPosition = function () {
        this.cursorPosition.x = 0;
        this.cursorPosition.y = 0;
    };
    SeekBarHandler.prototype.updateCursorPosition = function (direction, seekBarWrapper) {
        this.cursorPosition.x += this.getIncrement(direction, seekBarWrapper);
    };
    SeekBarHandler.prototype.initializeCursorPosition = function (seekBarWrapper) {
        var playbackPositionMarker = getPlaybackPositionMarker(seekBarWrapper);
        var rect = (0, navigationalgorithm_1.getBoundingRectFromElement)(playbackPositionMarker);
        var startX = rect.x + (rect.width / 2);
        var startY = rect.y;
        this.cursorPosition.x = startX;
        this.cursorPosition.y = startY;
    };
    SeekBarHandler.prototype.initializeOrUpdateCursorPosition = function (seekBarWrapper, direction) {
        if (this.isScrubbing) {
            this.updateCursorPosition(direction, seekBarWrapper);
        }
        else {
            this.initializeCursorPosition(seekBarWrapper);
        }
        this.isScrubbing = true;
    };
    SeekBarHandler.prototype.getCursorPositionMouseEventInit = function () {
        return {
            clientX: this.cursorPosition.x,
            clientY: this.cursorPosition.y,
        };
    };
    SeekBarHandler.prototype.dispatchMouseMoveEvent = function (seekBar) {
        seekBar.dispatchEvent(new MouseEvent('mousemove', this.getCursorPositionMouseEventInit()));
    };
    SeekBarHandler.prototype.dispatchMouseClickEvent = function (seekBar) {
        var _this = this;
        var mouseDownHandler = function () {
            var mouseEventInit = _this.getCursorPositionMouseEventInit();
            document.dispatchEvent(new MouseEvent('mouseup', mouseEventInit));
            _this.eventSubscriber.off(seekBar, 'mousedown', mouseDownHandler);
            _this.stopSeeking(seekBar);
        };
        this.eventSubscriber.on(seekBar, 'mousedown', mouseDownHandler);
        seekBar.dispatchEvent(new MouseEvent('mousedown'));
    };
    SeekBarHandler.prototype.stopSeeking = function (seekBar) {
        this.resetCursorPosition();
        this.isScrubbing = false;
        this.dispatchMouseLeaveEvent(seekBar);
    };
    SeekBarHandler.prototype.dispatchMouseLeaveEvent = function (seekBar) {
        seekBar.dispatchEvent(new MouseEvent('mouseleave'));
    };
    /**
     * Releases the SeekBraHandler, making sure all event subscribers are removed.
     */
    SeekBarHandler.prototype.release = function () {
        this.eventSubscriber.release();
        this.rootNavigationGroup.onAction = undefined;
        this.rootNavigationGroup.onNavigation = undefined;
    };
    return SeekBarHandler;
}());
exports.SeekBarHandler = SeekBarHandler;
function isSeekBarWrapper(element) {
    return Array.from(element.classList).findIndex(function (className) { return /-ui-seekbar$/.test(className); }) > -1;
}
function getSeekBar(seekBarWrapper) {
    return seekBarWrapper.children.item(0);
}
function getPlaybackPositionMarker(seekBarWrapper) {
    return seekBarWrapper.querySelector('[class*="seekbar-playbackposition-marker"]');
}
