"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.scrollIntoView = exports.scrollToCenter = exports.scrollTo = void 0;
var featureQueries_1 = require("./featureQueries");
var layout_1 = require("./layout");
var tiles_1 = require("./tiles");
/*
  a fallback for manually smooth scrolling
*/
var ease = function (x) { return 0.5 * (1 - Math.cos(Math.PI * x)); };
var DURATION = 500;
var fallbackSmoothScroll = function (el, position) {
    var start = el.scrollLeft;
    var end = position;
    var distance = end - start;
    var startTime = performance.now();
    var scrollStep = function () {
        var currentTime = performance.now();
        // add a max speed? increase time proportially to the distance??
        var elapsed = Math.min(1, (currentTime - startTime) / DURATION);
        var progress = ease(elapsed);
        var currentPosition = start + distance * progress;
        el.scrollLeft = currentPosition;
        if (currentPosition !== end) {
            requestAnimationFrame(scrollStep);
        }
    };
    scrollStep();
};
/*
  scroll the element (horizontally) to the specified position
  uses fallbacks if browser doesn't support el.scrollTo() or smooth scrolling
*/
var scrollToImmediate = function (el, position) {
    if (el.scrollTo) {
        el.scrollTo({ left: position, behavior: 'auto' });
    }
    else {
        el.scrollLeft = position;
    }
};
var scrollToSmooth = function (el, position) {
    if (el.scrollTo && featureQueries_1.supportsSmoothScroll()) {
        el.scrollTo({ left: position, behavior: 'smooth' });
    }
    else {
        fallbackSmoothScroll(el, position);
    }
};
/*
  scroll the element (horizontally) to the specified position, optionally doing it smoothly
  uses fallbacks if browser doesn't support el.scrollTo() or smooth scrolling
*/
exports.scrollTo = function (el, position, smooth) {
    if (layout_1.scrollPosition(el) === position)
        return;
    if (smooth && !featureQueries_1.prefersReducedMotion()) {
        scrollToSmooth(el, position);
    }
    else {
        scrollToImmediate(el, position);
    }
};
/*
  scroll the element (horizontally) so that the target element is centered (or as close to) in the container
*/
exports.scrollToCenter = function (container, target, smooth) {
    if (smooth === void 0) { smooth = true; }
    if (!container || !target)
        return;
    exports.scrollTo(container, layout_1.alignAtCenter(container, target), smooth);
};
/*
  scroll the element (horizontally) so that the target is entirely visibile
*/
exports.scrollIntoView = function (container, tile, smooth) {
    var _a;
    if (smooth === void 0) { smooth = true; }
    if (!container || !tile)
        return;
    var targetOffset = layout_1.getTileTargetZoneOffsets(container);
    var isTooFarLeft = layout_1.leftEdgeOffset(tile) < layout_1.targetZoneLeftEdge(container, targetOffset);
    var isTooFarRight = layout_1.rightEdgeOffset(tile) > layout_1.targetZoneRightEdge(container, targetOffset);
    if (isTooFarLeft) {
        exports.scrollTo(container, layout_1.alignAtTargetZoneLeftEdge(container, targetOffset, tile), smooth);
    }
    else if (isTooFarRight && !featureQueries_1.scrollSnapEnabled()) {
        exports.scrollTo(container, layout_1.alignAtTargetZoneRightEdge(container, targetOffset, tile), smooth);
    }
    else if (isTooFarRight && featureQueries_1.scrollSnapEnabled()) {
        var tiles = tiles_1.getTiles(container);
        var projectedLeftEdge_1 = layout_1.projectTargetZoneLeftEdge(layout_1.alignAtTargetZoneRightEdge(container, targetOffset, tile), targetOffset);
        var nextLeftTile = (_a = tiles.find(function (tile) { return layout_1.leftEdgeOffset(tile) >= projectedLeftEdge_1; })) !== null && _a !== void 0 ? _a : tile;
        exports.scrollTo(container, layout_1.alignAtTargetZoneLeftEdge(container, targetOffset, nextLeftTile), true);
    }
};
