import * as React from 'react';
import { JSX, DependencyList } from 'react';

type NonNullish<T> = Exclude<T, null | undefined>

type ElementNames = keyof JSX.IntrinsicElements

type EventNames<ElementName extends ElementNames> = {
  [K in keyof JSX.IntrinsicElements[ElementName]]: K extends `on${string}` ? K : never
}[keyof JSX.IntrinsicElements[ElementName]]

type AnyEventHandler<T = Element> = React.EventHandler<React.SyntheticEvent<T>>

type EventHandlers<T = Element> = {
  [K in keyof Required<React.DOMAttributes<T>> as K extends `on${string}` ? K : never]: Required<React.DOMAttributes<T>>[K]
}

type EventCallback<
  ElementName extends ElementNames,
  EventName extends EventNames<ElementName>,
> = NonNullish<JSX.IntrinsicElements[ElementName][EventName]>

declare function useEventCallback(handler: AnyEventHandler<HTMLElement>): AnyEventHandler<HTMLElement>;
declare function useEventCallback<ElementName extends ElementNames, EventName extends EventNames<ElementName>>(callback: EventCallback<ElementName, EventName>, deps?: DependencyList): EventCallback<ElementName, EventName>;
declare function useEventCallback<EventName extends keyof EventHandlers<HTMLElement>>(event: EventName, callback: EventHandlers[EventName], deps?: DependencyList): EventHandlers[EventName];
declare function useEventCallback<ElementName extends ElementNames, EventName extends EventNames<ElementName>>(element: ElementName, event: EventName, callback: EventCallback<ElementName, EventName>, deps?: DependencyList): EventCallback<ElementName, EventName>;

export { useEventCallback };
