"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArticleRectObserver = void 0;
const EventEmitter_1 = require("../EventEmitter");
const resize_observer_polyfill_1 = __importDefault(require("resize-observer-polyfill"));
class ArticleRectObserver extends EventEmitter_1.EventEmitter {
    constructor() {
        super();
        this.articleWidth = 0;
        this.registry = new Map();
        this.scrollPos = window.scrollY;
        this.animationFrame = NaN;
        this.parent = undefined;
        this.sectionsScrollMap = new Map();
        this.handleScroll = (scroll) => {
            this.setScroll(scroll / this.articleWidth);
        };
        this.resizeObserver = new resize_observer_polyfill_1.default(this.handleResize.bind(this));
    }
    get scroll() {
        return this.scrollPos;
    }
    getSectionScroll(sectionId) {
        const sectionTop = this.sectionsScrollMap.get(sectionId);
        if (sectionTop === undefined)
            return 0;
        return -(sectionTop / this.articleWidth - this.scrollPos);
    }
    getSectionTop(sectionId) {
        const sectionTop = this.sectionsScrollMap.get(sectionId);
        return sectionTop !== null && sectionTop !== void 0 ? sectionTop : 0;
    }
    get width() {
        return this.articleWidth;
    }
    setScroll(scroll) {
        this.scrollPos = scroll;
    }
    init(parent) {
        this.parent = parent;
        const onScroll = () => {
            this.handleScroll(window.scrollY);
            if (!isNaN(this.animationFrame))
                return;
            this.animationFrame = window.requestAnimationFrame(() => {
                this.animationFrame = NaN;
                this.emit('scroll', undefined);
            });
        };
        window.addEventListener('scroll', onScroll);
        return () => {
            this.parent = undefined;
            window.removeEventListener('scroll', onScroll);
            if (!isNaN(this.animationFrame)) {
                window.cancelAnimationFrame(this.animationFrame);
                this.animationFrame = NaN;
            }
        };
    }
    register(el, sectionId) {
        this.registry.set(sectionId, el);
        this.resizeObserver.observe(el);
        return () => {
            this.registry.delete(sectionId);
            this.resizeObserver.unobserve(el);
        };
    }
    handleResize() {
        if (!this.parent)
            return;
        const parentBoundary = this.parent.getBoundingClientRect();
        this.articleWidth = parentBoundary.width;
        this.setScroll(window.scrollY / this.articleWidth);
        this.emit('resize', parentBoundary);
        for (const sectionId of this.registry.keys()) {
            const el = this.registry.get(sectionId);
            if (!el)
                continue;
            const rect = el.getBoundingClientRect();
            this.sectionsScrollMap.set(sectionId, rect.top - parentBoundary.top);
        }
    }
    ;
}
exports.ArticleRectObserver = ArticleRectObserver;
