"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useMemo, useSyncExternalStore, } from "react";
const NAVIGATION_EVENT = "parhelia:navigation";
const noopRouter = {
    push: () => { },
    replace: () => { },
};
const emptyNavigation = {
    pathname: "",
    search: "",
    router: noopRouter,
};
const NavigationContext = createContext(null);
function emitNavigationChange() {
    if (typeof window !== "undefined") {
        window.dispatchEvent(new Event(NAVIGATION_EVENT));
    }
}
function ensureBrowserHistoryPatched() {
    if (typeof window === "undefined") {
        return;
    }
    const history = window.history;
    if (history.__parheliaNavigationPatched) {
        return;
    }
    history.__parheliaNavigationPatched = true;
    history.__parheliaOriginalPushState = history.pushState.bind(history);
    history.__parheliaOriginalReplaceState = history.replaceState.bind(history);
    history.pushState = ((...args) => {
        const previousUrl = window.location.href;
        history.__parheliaOriginalPushState?.(...args);
        if (window.location.href !== previousUrl) {
            emitNavigationChange();
        }
    });
    history.replaceState = ((...args) => {
        const previousUrl = window.location.href;
        history.__parheliaOriginalReplaceState?.(...args);
        if (window.location.href !== previousUrl) {
            emitNavigationChange();
        }
    });
}
if (typeof window !== "undefined") {
    ensureBrowserHistoryPatched();
}
function navigateWithHistory(href, replace) {
    if (typeof window === "undefined")
        return;
    ensureBrowserHistoryPatched();
    const url = new URL(href, window.location.href);
    const nextUrl = `${url.pathname}${url.search}${url.hash}`;
    const historyState = window.history.state;
    if (replace) {
        window.history.replaceState(historyState, "", nextUrl);
    }
    else {
        window.history.pushState(historyState, "", nextUrl);
    }
}
const browserRouter = {
    push: (href) => navigateWithHistory(href, false),
    replace: (href) => navigateWithHistory(href, true),
};
let lastBrowserNavigationSnapshot = null;
function subscribeToBrowserNavigation(onStoreChange) {
    if (typeof window === "undefined") {
        return () => { };
    }
    ensureBrowserHistoryPatched();
    const handleChange = () => onStoreChange();
    window.addEventListener("popstate", handleChange);
    window.addEventListener(NAVIGATION_EVENT, handleChange);
    return () => {
        window.removeEventListener("popstate", handleChange);
        window.removeEventListener(NAVIGATION_EVENT, handleChange);
    };
}
function getBrowserNavigationSnapshot() {
    if (typeof window === "undefined") {
        return emptyNavigation;
    }
    ensureBrowserHistoryPatched();
    const pathname = window.location.pathname;
    const search = window.location.search;
    if (lastBrowserNavigationSnapshot &&
        lastBrowserNavigationSnapshot.pathname === pathname &&
        lastBrowserNavigationSnapshot.search === search) {
        return lastBrowserNavigationSnapshot;
    }
    lastBrowserNavigationSnapshot = {
        pathname,
        search,
        router: browserRouter,
    };
    return lastBrowserNavigationSnapshot;
}
function useBrowserNavigation() {
    return useSyncExternalStore(subscribeToBrowserNavigation, getBrowserNavigationSnapshot, () => emptyNavigation);
}
export function NavigationProvider({ value, children, }) {
    const search = value.searchParams.toString();
    const normalizedValue = useMemo(() => ({
        pathname: value.pathname,
        search,
        router: value.router,
    }), [value.pathname, search, value.router]);
    return (_jsx(NavigationContext.Provider, { value: normalizedValue, children: children }));
}
function useNavigationValue() {
    const context = useContext(NavigationContext);
    const browserNavigation = useBrowserNavigation();
    return context ?? browserNavigation;
}
export function useRouter() {
    return useNavigationValue().router;
}
export function usePathname() {
    return useNavigationValue().pathname;
}
export function useSearchParams() {
    const search = useNavigationValue().search;
    return useMemo(() => new URLSearchParams(search), [search]);
}
export function notifyNavigationChanged() {
    emitNavigationChange();
}
//# sourceMappingURL=navigation.js.map