// #region Imports
import { on } from '@breadstone/mosaik-elements';
import { Routes } from './Routes';
// #endregion
/**
 * We cache the origin since it cannot change at runtime.
 */
const ORIGIN = location.origin || `${location.protocol}//${location.host}`;
/**
 * A root-level router that installs global event listeners to intercept
 * navigation via anchor clicks and browser history changes.
 *
 * This class extends `Routes` so that it can also hold a route configuration.
 *
 * There should only be one `Router` instance on a page because it installs
 * global event listeners on `window`. Nested routes should use the `Routes`
 * class instead.
 *
 * @public
 */
export class Router extends Routes {
    // #region Fields
    _windowClickSubscription = null;
    _windowPopStateSubscription = null;
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    hostConnected() {
        super.hostConnected();
        this._windowClickSubscription = on(window, 'click', (e) => this.onWindowClick(e));
        this._windowPopStateSubscription = on(window, 'popstate', (e) => this.onWindowPopState(e));
        // Kick off routed rendering by navigating to the current URL.
        void this.goto(window.location.pathname);
    }
    /**
     * @public
     * @override
     */
    hostDisconnected() {
        super.hostDisconnected();
        this._windowClickSubscription?.dispose();
        this._windowPopStateSubscription?.dispose();
    }
    /**
     * Intercepts anchor clicks for in-page navigation.
     *
     * @private
     */
    onWindowClick(event) {
        const isNonNavigationClick = event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey;
        if (event.defaultPrevented || isNonNavigationClick) {
            return;
        }
        const anchor = this.findAnchor(event.composedPath());
        if (!anchor) {
            return;
        }
        if (anchor.target !== '' ||
            anchor.download ||
            anchor.rel === 'external' ||
            anchor.href === '' ||
            anchor.href?.startsWith('mailto:') ||
            anchor.href?.startsWith('tel:') ||
            (anchor.origin && anchor.origin !== ORIGIN)) {
            return;
        }
        event.preventDefault();
        if (anchor.href !== window.location.href) {
            window.history.pushState({}, '', anchor.href);
            void this.goto(anchor.pathname);
        }
    }
    /**
     * Handles browser history navigation (back/forward).
     *
     * @private
     */
    onWindowPopState(_event) {
        void this.goto(window.location.pathname);
    }
    /**
     * Finds an anchor element in the event's composed path.
     *
     * @param path - The composed event path.
     * @returns An `IRouterLinkLike` object if a valid anchor is found, otherwise `undefined`.
     *
     * @private
     */
    findAnchor(path) {
        const anchor = path.find((x) => x instanceof HTMLAnchorElement && x.hasAttribute('href'));
        if (!anchor) {
            return undefined;
        }
        return {
            download: anchor.download,
            href: anchor.href,
            rel: anchor.rel,
            target: anchor.target,
            origin: anchor.origin,
            pathname: anchor.pathname,
            search: anchor.search
        };
    }
}
//# sourceMappingURL=Router.js.map