"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SLOWDOWN_PIXEL_OFFSET = exports.MAX_SCROLL_ATTEMPTS = void 0;
exports.scrollByCoordinates = scrollByCoordinates;
exports.getElementLocationAndSizeLimitedToDeviceScreen = getElementLocationAndSizeLimitedToDeviceScreen;
exports.getScrollExecutionCoordinates = getScrollExecutionCoordinates;
exports.scrollInDirection = scrollInDirection;
exports.convertElementLocationAndSizeToBoundingBox = convertElementLocationAndSizeToBoundingBox;
const ScrollStepDescriptor_1 = require("@mablhq/test-model/types/mobile/ScrollStepDescriptor");
exports.MAX_SCROLL_ATTEMPTS = 100;
exports.SLOWDOWN_PIXEL_OFFSET = 5;
const pauseDurationMillis = 100;
const pixelsPerSecond = 2_000;
const minScrollDuration = 50;
const pauseForScrollAnimationMs = 700;
const centerScrollPercentage = 0.5;
const defaultLowerScrollPercentage = 0.2;
const defaultUpperScrollPercentage = 0.8;
async function scrollByCoordinates(driver, coordinates) {
    const { fromX, fromY, slowDownValX, slowDownValY, toX, toY } = coordinates;
    const maxDistanceToScroll = Math.max(Math.abs(toX - fromX), Math.abs(toY - fromY));
    const scrollDuration = Math.max(Math.round((maxDistanceToScroll / pixelsPerSecond) * 1000), minScrollDuration);
    await driver.pause(pauseForScrollAnimationMs);
    await driver.performActions([
        {
            type: 'pointer',
            id: 'finger1',
            parameters: { pointerType: 'touch' },
            actions: [
                { type: 'pointerMove', duration: 0, x: fromX, y: fromY },
                { type: 'pointerDown', button: 0 },
                { type: 'pause', duration: pauseDurationMillis },
                {
                    type: 'pointerMove',
                    duration: scrollDuration,
                    x: slowDownValX,
                    y: slowDownValY,
                },
                { type: 'pause', duration: pauseDurationMillis },
                { type: 'pointerMove', duration: 100, x: toX, y: toY },
                { type: 'pause', duration: pauseDurationMillis },
                { type: 'pointerUp', button: 0 },
            ],
        },
    ]);
    await driver.pause(pauseForScrollAnimationMs);
}
async function getElementLocationAndSizeLimitedToDeviceScreen(deviceScreenSize, element, elementBoundingBox) {
    let elementLocation = { x: 0, y: 0 };
    let size = { height: deviceScreenSize.height, width: deviceScreenSize.width };
    if (elementBoundingBox) {
        elementLocation = { x: elementBoundingBox.x, y: elementBoundingBox.y };
        size = {
            width: elementBoundingBox.width,
            height: elementBoundingBox.height,
        };
    }
    else if (element) {
        elementLocation = await element.getLocation();
        size = await element.getSize();
    }
    const locationX = Math.min(Math.max(0, elementLocation.x), deviceScreenSize.width);
    const locationY = Math.min(Math.max(0, elementLocation.y), deviceScreenSize.height);
    const sizeWidth = Math.min(Math.max(0, size.width), deviceScreenSize.width - locationX);
    const sizeHeight = Math.min(Math.max(0, size.height), deviceScreenSize.height - locationY);
    return {
        elementLocation: { x: locationX, y: locationY },
        size: { width: sizeWidth, height: sizeHeight },
    };
}
async function getScrollExecutionCoordinates(deviceScreenSize, scrollConfiguration) {
    const { boundingBox, element, scrollDirection, scrollPercentages } = scrollConfiguration;
    let elementLocation = { x: 0, y: 0 };
    let size = deviceScreenSize;
    if (element || boundingBox) {
        const elementLocationAndSize = await getElementLocationAndSizeLimitedToDeviceScreen(deviceScreenSize, element, boundingBox);
        elementLocation = elementLocationAndSize.elementLocation;
        size = elementLocationAndSize.size;
    }
    let fromXPercent, fromYPercent, toXPercent, toYPercent;
    switch (scrollDirection) {
        case ScrollStepDescriptor_1.ScrollDirection.Down:
            fromXPercent = scrollPercentages?.from.xPercent ?? centerScrollPercentage;
            fromYPercent =
                scrollPercentages?.from.yPercent ?? defaultUpperScrollPercentage;
            toXPercent = scrollPercentages?.to.xPercent ?? centerScrollPercentage;
            toYPercent =
                scrollPercentages?.to.yPercent ?? defaultLowerScrollPercentage;
            break;
        case ScrollStepDescriptor_1.ScrollDirection.Up:
            fromXPercent = scrollPercentages?.from.xPercent ?? centerScrollPercentage;
            fromYPercent =
                scrollPercentages?.from.yPercent ?? defaultLowerScrollPercentage;
            toXPercent = scrollPercentages?.to.xPercent ?? centerScrollPercentage;
            toYPercent =
                scrollPercentages?.to.yPercent ?? defaultUpperScrollPercentage;
            break;
        case ScrollStepDescriptor_1.ScrollDirection.Left:
            fromXPercent =
                scrollPercentages?.from.xPercent ?? defaultLowerScrollPercentage;
            fromYPercent = scrollPercentages?.from.yPercent ?? centerScrollPercentage;
            toXPercent =
                scrollPercentages?.to.xPercent ?? defaultUpperScrollPercentage;
            toYPercent = scrollPercentages?.to.yPercent ?? centerScrollPercentage;
            break;
        case ScrollStepDescriptor_1.ScrollDirection.Right:
            fromXPercent =
                scrollPercentages?.from.xPercent ?? defaultUpperScrollPercentage;
            fromYPercent = scrollPercentages?.from.yPercent ?? centerScrollPercentage;
            toXPercent =
                scrollPercentages?.to.xPercent ?? defaultLowerScrollPercentage;
            toYPercent = scrollPercentages?.to.yPercent ?? centerScrollPercentage;
            break;
        default:
            throw new Error(`Unknown scroll direction: [${scrollDirection}]`);
    }
    const fromX = elementLocation.x + Math.round(size.width * fromXPercent);
    const fromY = elementLocation.y + Math.round(size.height * fromYPercent);
    const toX = elementLocation.x + Math.round(size.width * toXPercent);
    const toY = elementLocation.y + Math.round(size.height * toYPercent);
    const slowDownValX = fromX <= toX
        ? toX - Math.min(exports.SLOWDOWN_PIXEL_OFFSET, toX - fromX)
        : toX + Math.min(exports.SLOWDOWN_PIXEL_OFFSET, fromX - toX);
    const slowDownValY = fromY <= toY
        ? toY - Math.min(exports.SLOWDOWN_PIXEL_OFFSET, toY - fromY)
        : toY + Math.min(exports.SLOWDOWN_PIXEL_OFFSET, fromY - toY);
    return { fromX, fromY, slowDownValX, slowDownValY, toX, toY };
}
async function scrollInDirection(driver, windowSize, scrollConfiguration = {
    scrollDirection: ScrollStepDescriptor_1.ScrollDirection.Down,
}) {
    const scrollCoordinates = await getScrollExecutionCoordinates(windowSize, scrollConfiguration);
    await scrollByCoordinates(driver, scrollCoordinates);
}
function convertElementLocationAndSizeToBoundingBox(elementLocationAndSize) {
    return {
        x: elementLocationAndSize.elementLocation.x,
        y: elementLocationAndSize.elementLocation.y,
        width: elementLocationAndSize.size.width,
        height: elementLocationAndSize.size.height,
    };
}
