import { h, createContext, VNode, ComponentType, createElement } from 'preact';
import { useState, useEffect } from 'preact/hooks';

const DEFAULT_ROUTE = '/';

interface Props {
    /**
     * Specifies all URLs and their respectful components.
     */
    routes: {
        [DEFAULT_ROUTE]: VNode;
        [key: string]: VNode;
    };
    onChange?: (route: string) => void;
}

/**
 * Stores current URL of the router and allows to change it programmatically.
 */
export const RouterContext = createContext<{ route: string, setRoute: (route: string) => void }>(
    { route: DEFAULT_ROUTE, setRoute: (_: string) => undefined });

/**
 * Oversimplified router component.
 */
export const Router = ({ routes, onChange }: Props) => {
    const [route, setRoute] = useState(DEFAULT_ROUTE);
    useEffect(() => onChange?.(route), [route]);

    return (
        <RouterContext.Provider value={{ route, setRoute }}>
            {routes[route]}
        </RouterContext.Provider>
    );
};

export const RouteComponent = (props: { component: ComponentType<null> }) =>
    createElement(props.component, null);

/**
 * Render anchor with click handler to switch route based on `href` attribute.
 * We intentionally override final `href`, so links within widget won't lead to actual
 * pages on website.
 */
export const RouteLink = ({ href, children, ...rest }: h.JSX.HTMLAttributes<HTMLAnchorElement>) => (
    <RouterContext.Consumer>
        {({ setRoute }) => (
            <a href='javascript:' onClick={() => href && setRoute(href)} {...rest}>{children}</a>
        )}
    </RouterContext.Consumer>
);