import { Graph } from "../graph";
import { TGraphColors, TGraphConstants } from "../graphConfig";
import { GraphEventsDefinitions } from "../graphEvents";
import { CoreComponent } from "../lib";
import { Component, TComponentState } from "../lib/Component";
import { ICamera, TCameraState } from "./camera/CameraService";
import "./Layer.css";
export type LayerPropsElementProps = {
    zIndex: number;
    classNames?: string[];
    root?: HTMLElement;
    transformByCameraPosition?: boolean;
};
export type LayerPropsHtmlElementProps = LayerPropsElementProps & {
    /**
     * Minimum camera scale at which the HTML layer becomes active.
     * When camera scale is below this value, the HTML layer is disabled
     * and won't receive updates (improving performance when zoomed out).
     *
     * @example
     * ```typescript
     * // HTML layer only active when zoomed in (scale >= 0.5)
     * html: { zIndex: 1, activationScale: 0.5 }
     * ```
     */
    activationScale?: number;
};
export type LayerProps = {
    canvas?: LayerPropsElementProps & {
        respectPixelRatio?: boolean;
        alpha?: boolean;
        desynchronized?: boolean;
        willReadFrequently?: boolean;
    };
    html?: LayerPropsHtmlElementProps;
    root?: HTMLElement;
    camera: ICamera;
    graph: Graph;
};
export type LayerContext = {
    graph: Graph;
    camera: ICamera;
    constants: TGraphConstants;
    colors: TGraphColors;
    graphCanvas: HTMLCanvasElement;
    ctx: CanvasRenderingContext2D;
    layer: Layer;
};
/**
 * Utility type to extract public props for a Layer constructor.
 * Excludes internal props that are provided by the graph instance:
 * - root: managed by the layers service
 * - camera: provided by the graph's camera service
 * - graph: provided by the graph instance
 *
 * The root prop is made optional as it can be overridden by the user.
 *
 * @template T - Layer constructor type
 */
export type LayerPublicProps<T extends Constructor<Layer>> = T extends Constructor<Layer<infer Props>> ? Omit<Props, "root" | "camera" | "graph"> & {
    root?: Props["root"];
} : never;
export type LayerConstructor<T extends Constructor<Layer>> = T extends Constructor<Layer> ? T : never;
export declare class Layer<Props extends LayerProps = LayerProps, Context extends LayerContext = LayerContext, State extends TComponentState = TComponentState> extends Component<Props, State, Context> {
    static id?: string;
    protected canvas: HTMLCanvasElement;
    protected html: HTMLElement;
    protected root?: HTMLDivElement;
    protected attached: boolean;
    /**
     * Indicates whether the HTML layer is currently active based on camera scale.
     * When false, the HTML layer is hidden and won't receive updates.
     */
    protected htmlActive: boolean;
    /**
     * AbortController used to manage event listeners.
     * All event listeners (both graph.on and DOM addEventListener) are registered with this controller's signal.
     * When the layer is unmounted, the controller is aborted, which automatically removes all event listeners.
     */
    protected eventAbortController: AbortController;
    /**
     * A wrapper for this.props.graph.on that automatically includes the AbortController signal.
     * The method is named onGraphEvent to indicate it's specifically for graph events.
     * This simplifies event subscription and ensures proper cleanup when the layer is unmounted.
     *
     * IMPORTANT: Always use this method in the afterInit() method, NOT in the constructor.
     * This ensures that event subscriptions are properly set up when the layer is reattached.
     * When a layer is unmounted, the AbortController is aborted and a new one is created.
     * When the layer is reattached, afterInit() is called again, which sets up new subscriptions
     * with the new AbortController.
     *
     * @param eventName - The name of the event to subscribe to
     * @param handler - The event handler function
     * @param options - Additional options (optional)
     * @returns The result of graph.on call (an unsubscribe function)
     */
    protected onGraphEvent<EventName extends keyof GraphEventsDefinitions, Cb extends GraphEventsDefinitions[EventName]>(eventName: EventName, handler: Cb, options?: Omit<AddEventListenerOptions, "signal">): () => void;
    hide(): void;
    isHidden(): boolean;
    show(): void;
    /**
     * A wrapper for HTMLElement.addEventListener that automatically includes the AbortController signal.
     * This method is for adding event listeners to the HTML element of the layer.
     * It simplifies event subscription and ensures proper cleanup when the layer is unmounted.
     *
     * IMPORTANT: Always use this method in the afterInit() method, NOT in the constructor.
     * This ensures that event subscriptions are properly set up when the layer is reattached.
     * When a layer is unmounted, the AbortController is aborted and a new one is created.
     * When the layer is reattached, afterInit() is called again, which sets up new subscriptions
     * with the new AbortController.
     *
     * @param eventName - The name of the DOM event to subscribe to
     * @param handler - The event handler function
     * @param options - Additional options (optional)
     */
    protected onHtmlEvent<K extends keyof HTMLElementEventMap>(eventName: K, handler: ((this: HTMLElement, ev: HTMLElementEventMap[K]) => void) | EventListenerObject, options?: Omit<AddEventListenerOptions, "signal">): void;
    /**
     * A wrapper for HTMLCanvasElement.addEventListener that automatically includes the AbortController signal.
     * This method is for adding event listeners to the canvas element of the layer.
     * It simplifies event subscription and ensures proper cleanup when the layer is unmounted.
     *
     * IMPORTANT: Always use this method in the afterInit() method, NOT in the constructor.
     * This ensures that event subscriptions are properly set up when the layer is reattached.
     * When a layer is unmounted, the AbortController is aborted and a new one is created.
     * When the layer is reattached, afterInit() is called again, which sets up new subscriptions
     * with the new AbortController.
     *
     * @param eventName - The name of the DOM event to subscribe to
     * @param handler - The event handler function
     * @param options - Additional options (optional)
     */
    protected onCanvasEvent<K extends keyof HTMLElementEventMap>(eventName: K, handler: ((this: HTMLCanvasElement, ev: HTMLElementEventMap[K]) => void) | EventListenerObject, options?: Omit<AddEventListenerOptions, "signal">): void;
    /**
     * A wrapper for HTMLElement.addEventListener that automatically includes the AbortController signal.
     * This method is for adding event listeners to the root element of the layer.
     * It simplifies event subscription and ensures proper cleanup when the layer is unmounted.
     *
     * IMPORTANT: Always use this method in the afterInit() method, NOT in the constructor.
     * This ensures that event subscriptions are properly set up when the layer is reattached.
     * When a layer is unmounted, the AbortController is aborted and a new one is created.
     * When the layer is reattached, afterInit() is called again, which sets up new subscriptions
     * with the new AbortController.
     *
     * @param eventName - The name of the DOM event to subscribe to
     * @param handler - The event handler function
     * @param options - Additional options (optional)
     */
    protected onRootEvent<K extends keyof HTMLElementEventMap>(eventName: K, handler: ((this: HTMLElement, ev: HTMLElementEventMap[K]) => void) | EventListenerObject, options?: Omit<AddEventListenerOptions, "signal">): void;
    /**
     * Subscribes to a signal (with .subscribe) and automatically unsubscribes when the layer's AbortController is aborted.
     *
     * Usage:
     *   this.onSignal(signal, handler)
     *
     * @template S - Signal type (must have .subscribe method)
     * @template T - Value type of the signal
     * @param signal - Signal with .subscribe method (returns unsubscribe function)
     * @param handler - Handler function to call on signal change
     * @returns The unsubscribe function (called automatically on abort)
     */
    protected onSignal<S extends {
        subscribe: (handler: (value: T) => void) => () => void;
    }, T = S extends {
        subscribe: (handler: (value: infer U) => void) => () => void;
    } ? U : unknown>(signal: S, handler: (value: T) => void): () => void;
    constructor(props: Props, parent?: CoreComponent);
    protected sizeTouched: boolean;
    updateSize: () => void;
    /**
     * Called after initialization and when the layer is reattached.
     * This is the proper place to set up event subscriptions using onGraphEvent().
     *
     * When a layer is unmounted, the AbortController is aborted and a new one is created.
     * When the layer is reattached, this method is called again, which sets up new subscriptions
     * with the new AbortController.
     *
     * All derived Layer classes should call super.afterInit() at the end of their afterInit method.
     */
    protected afterInit(): void;
    private readonly stopCameraMoving;
    protected moving: boolean;
    protected scheduleCameraChange(camera: TCameraState): void;
    private handleCommittedCameraChange;
    private applyCameraTransform;
    /**
     * Called when committed camera state changes (`graph.$camera` signal).
     * Override in derived layers to react to pan, zoom, and resize.
     *
     * Built-in HTML/canvas transforms (`transformByCameraPosition`, `activationScale`)
     * are applied before this hook via `applyCameraTransform`.
     *
     * @param camera - Committed camera state (same as `graph.$camera.value`)
     */
    protected onCameraChange(_camera: TCameraState): void;
    /**
     * Called when the HTML layer's active state changes based on camera scale.
     * Override this method to implement custom behavior when the layer activates/deactivates.
     *
     * @param active - Whether the HTML layer is now active
     */
    protected onHtmlActiveChange(active: boolean): void;
    /**
     * Returns whether the HTML layer is currently active.
     * The layer is inactive when camera scale is below the activationScale threshold.
     */
    isHtmlActive(): boolean;
    protected init(): void;
    protected unmountLayer(): void;
    protected unmount(): void;
    getCanvas(): HTMLCanvasElement;
    getHTML(): HTMLElement;
    attachLayer(root: HTMLElement): void;
    detachLayer(): void;
    protected createCanvas(params: LayerProps["canvas"]): HTMLCanvasElement;
    protected createHTML(params: LayerProps["html"]): HTMLDivElement;
    getDRP(): number;
    protected applyTransform(x: number, y: number, scale: number, respectPixelRatio?: boolean): void;
    protected updateCanvasSize(): void;
    resetTransform(): void;
    protected render(): void;
}
