const easingFunctions = {
    linear: (t) => t,
    easeIn: (t) => t * t,
    easeOut: (t) => t * (2 - t),
    easeInOut: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
};
export function scrollTo(target, options = {}) {
    const { offset = 0, duration = 500, easing = "easeInOut", onComplete, } = options;
    let targetPosition;
    if (typeof target === "number") {
        targetPosition = target;
    }
    else {
        const element = typeof target === "string"
            ? document.querySelector(target)
            : target;
        if (!element) {
            console.warn("[Stylescape] scrollTo target not found:", target);
            return;
        }
        targetPosition =
            element.getBoundingClientRect().top + window.pageYOffset;
    }
    const startPosition = window.pageYOffset;
    const distance = targetPosition + offset - startPosition;
    const easingFn = easingFunctions[easing];
    let startTime = null;
    function animation(currentTime) {
        if (startTime === null)
            startTime = currentTime;
        const elapsed = currentTime - startTime;
        const progress = Math.min(elapsed / duration, 1);
        window.scrollTo(0, startPosition + distance * easingFn(progress));
        if (elapsed < duration) {
            requestAnimationFrame(animation);
        }
        else {
            onComplete?.();
        }
    }
    requestAnimationFrame(animation);
}
export function scrollToPosition(y, options = {}) {
    if (options.smooth && options.duration) {
        scrollTo(y, { duration: options.duration });
    }
    else {
        window.scrollTo({
            top: y,
            behavior: options.smooth ? "smooth" : "auto",
        });
    }
}
export function scrollToTop(options = {}) {
    scrollToPosition(0, options);
}
export function scrollToBottom(options = {}) {
    const documentHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
    scrollToPosition(documentHeight, options);
}
export class ScrollToTopButton {
    constructor(options = {}) {
        this.ticking = false;
        this.handleScroll = () => {
            if (!this.ticking) {
                requestAnimationFrame(() => {
                    this.checkScroll();
                    this.ticking = false;
                });
                this.ticking = true;
            }
        };
        this.handleClick = (event) => {
            event.preventDefault();
            if (this.options.smooth) {
                scrollTo(0, { duration: this.options.duration });
            }
            else {
                window.scrollTo(0, 0);
            }
        };
        this.button =
            typeof options.button === "string"
                ? document.querySelector(options.button)
                : (options.button ?? null);
        this.options = {
            button: this.button ?? document.createElement("button"),
            threshold: options.threshold ?? 300,
            smooth: options.smooth ?? true,
            duration: options.duration ?? 500,
            visibleClass: options.visibleClass ?? "scroll-to-top--visible",
        };
        if (!this.button) {
            console.warn("[Stylescape] ScrollToTopButton: button not found");
            return;
        }
        this.init();
    }
    show() {
        this.button?.classList.add(this.options.visibleClass);
        this.button?.setAttribute("aria-hidden", "false");
    }
    hide() {
        this.button?.classList.remove(this.options.visibleClass);
        this.button?.setAttribute("aria-hidden", "true");
    }
    destroy() {
        window.removeEventListener("scroll", this.handleScroll);
        this.button?.removeEventListener("click", this.handleClick);
        this.button = null;
    }
    static init() {
        const buttons = [];
        document
            .querySelectorAll('[data-ss="scroll-to-top"]')
            .forEach((el) => {
            const threshold = el.dataset.ssScrollThreshold;
            buttons.push(new ScrollToTopButton({
                button: el,
                threshold: threshold
                    ? parseInt(threshold, 10)
                    : undefined,
            }));
        });
        return buttons;
    }
    init() {
        if (!this.button)
            return;
        this.button.setAttribute("aria-label", this.button.getAttribute("aria-label") || "Scroll to top");
        this.button.setAttribute("aria-hidden", "true");
        this.checkScroll();
        window.addEventListener("scroll", this.handleScroll, {
            passive: true,
        });
        this.button.addEventListener("click", this.handleClick);
    }
    checkScroll() {
        const scrollY = window.pageYOffset || document.documentElement.scrollTop;
        if (scrollY > this.options.threshold) {
            this.show();
        }
        else {
            this.hide();
        }
    }
}
export function initScrollLinks() {
    document
        .querySelectorAll('[data-ss="scroll-to"]')
        .forEach((el) => {
        const target = el.dataset.ssScrollTarget || el.getAttribute("href");
        const offset = el.dataset.ssScrollOffset;
        const duration = el.dataset.ssScrollDuration;
        el.addEventListener("click", (event) => {
            event.preventDefault();
            if (target) {
                scrollTo(target, {
                    offset: offset ? parseInt(offset, 10) : 0,
                    duration: duration ? parseInt(duration, 10) : 500,
                });
            }
        });
    });
}
export function initScrollUtilities() {
    initScrollLinks();
    ScrollToTopButton.init();
}
export default {
    scrollTo,
    scrollToPosition,
    scrollToTop,
    scrollToBottom,
    ScrollToTopButton,
    initScrollLinks,
    initScrollUtilities,
};
//# sourceMappingURL=scroll.js.map