/// <reference path="./global.d.ts" />

import type { AbstractRenderer } from '@pixi/core';
import type { Dict } from '@pixi/utils';
import { DisplayObject } from '@pixi/display';
import { EventEmitter } from '@pixi/utils';
import { IPointData } from '@pixi/math';
import { Point } from '@pixi/math';

declare type Cursor = 'auto' | 'default' | 'none' | 'context-menu' | 'help' | 'pointer' | 'progress' | 'wait' | 'cell' | 'crosshair' | 'text' | 'vertical-text' | 'alias' | 'copy' | 'move' | 'no-drop' | 'not-allowed' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'nesw-resize' | 'col-resize' | 'nwse-resize' | 'row-resize' | 'all-scroll' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing';

export declare interface DelayedEvent {
    displayObject: DisplayObject;
    eventString: string;
    eventData: InteractionEvent;
}

export declare interface IHitArea {
    contains(x: number, y: number): boolean;
}

export declare type InteractionCallback = (interactionEvent: InteractionEvent, displayObject: DisplayObject, hit?: boolean) => void;

/**
 * Holds all information related to an Interaction event
 *
 * @memberof PIXI
 */
export declare class InteractionData {
    /** This point stores the global coords of where the touch/mouse event happened. */
    global: Point;
    /** The target Sprite that was interacted with. */
    target: DisplayObject;
    /**
     * When passed to an event handler, this will be the original DOM Event that was captured
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
     * @see https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent
     * @member {MouseEvent|TouchEvent|PointerEvent}
     */
    originalEvent: InteractivePointerEvent;
    /** Unique identifier for this interaction. */
    identifier: number;
    /**
     * Indicates whether or not the pointer device that created the event is the primary pointer.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary
     */
    isPrimary: boolean;
    /**
     * Indicates which button was pressed on the mouse or pointer device to trigger the event.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
     */
    button: number;
    /**
     * Indicates which buttons are pressed on the mouse or pointer device when the event is triggered.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
     */
    buttons: number;
    /**
     * The width of the pointer's contact along the x-axis, measured in CSS pixels.
     * radiusX of TouchEvents will be represented by this value.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width
     */
    width: number;
    /**
     * The height of the pointer's contact along the y-axis, measured in CSS pixels.
     * radiusY of TouchEvents will be represented by this value.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height
     */
    height: number;
    /**
     * The angle, in degrees, between the pointer device and the screen.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltX
     */
    tiltX: number;
    /**
     * The angle, in degrees, between the pointer device and the screen.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltY
     */
    tiltY: number;
    /**
     * The type of pointer that triggered the event.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType
     */
    pointerType: string;
    /**
     * Pressure applied by the pointing device during the event. A Touch's force property
     * will be represented by this value.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pressure
     */
    pressure: number;
    /**
     * From TouchEvents (not PointerEvents triggered by touches), the rotationAngle of the Touch.
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/Touch/rotationAngle
     */
    rotationAngle: number;
    /**
     * Twist of a stylus pointer.
     *
     * @see https://w3c.github.io/pointerevents/#pointerevent-interface
     */
    twist: number;
    /**
     * Barrel pressure on a stylus pointer.
     *
     * @see https://w3c.github.io/pointerevents/#pointerevent-interface
     */
    tangentialPressure: number;
    constructor();
    /**
     * The unique identifier of the pointer. It will be the same as `identifier`.
     *
     * @readonly
     * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerId
     */
    get pointerId(): number;
    /**
     * This will return the local coordinates of the specified displayObject for this InteractionData
     *
     * @param displayObject - The DisplayObject that you would like the local
     *  coords off
     * @param point - A Point object in which to store the value, optional (otherwise
     *  will create a new point)
     * @param globalPos - A Point object containing your custom global coords, optional
     *  (otherwise will use the current global coords)
     * @return - A point containing the coordinates of the InteractionData position relative
     *  to the DisplayObject
     */
    getLocalPosition<P extends IPointData = Point>(displayObject: DisplayObject, point?: P, globalPos?: IPointData): P;
    /**
     * Copies properties from normalized event data.
     *
     * @param {Touch|MouseEvent|PointerEvent} event - The normalized event data
     */
    copyEvent(event: Touch | InteractivePointerEvent): void;
    /** Resets the data for pooling. */
    reset(): void;
}

/**
 * Event class that mimics native DOM events.
 *
 * @memberof PIXI
 */
export declare class InteractionEvent {
    /**
     * Whether this event will continue propagating in the tree.
     *
     * Remaining events for the {@link stopsPropagatingAt} object
     * will still be dispatched.
     */
    stopped: boolean;
    /**
     * At which object this event stops propagating.
     *
     * @private
     */
    stopsPropagatingAt: DisplayObject;
    /**
     * Whether we already reached the element we want to
     * stop propagating at. This is important for delayed events,
     * where we start over deeper in the tree again.
     *
     * @private
     */
    stopPropagationHint: boolean;
    /**
     * The object which caused this event to be dispatched.
     * For listener callback see {@link PIXI.InteractionEvent.currentTarget}.
     */
    target: DisplayObject;
    /** The object whose event listener’s callback is currently being invoked. */
    currentTarget: DisplayObject;
    /** Type of the event. */
    type: string;
    /** {@link InteractionData} related to this event */
    data: InteractionData;
    constructor();
    /** Prevents event from reaching any objects other than the current object. */
    stopPropagation(): void;
    /** Resets the event. */
    reset(): void;
}

/**
 * The interaction manager deals with mouse, touch and pointer events.
 *
 * Any DisplayObject can be interactive if its `interactive` property is set to true.
 *
 * This manager also supports multitouch.
 *
 * An instance of this class is automatically created by default, and can be found at `renderer.plugins.interaction`
 *
 * @memberof PIXI
 */
export declare class InteractionManager extends EventEmitter {
    /**
     * Actively tracked InteractionData
     *
     * @private
     * @member {Object.<number,PIXI.InteractionData>}
     */
    readonly activeInteractionData: {
        [key: number]: InteractionData;
    };
    /**
     * Does the device support touch events
     * https://www.w3.org/TR/touch-events/
     */
    readonly supportsTouchEvents: boolean;
    /**
     * Does the device support pointer events
     * https://www.w3.org/Submission/pointer-events/
     */
    readonly supportsPointerEvents: boolean;
    /**
     * Pool of unused InteractionData
     *
     * @private
     */
    interactionDataPool: InteractionData[];
    /**
     * Internal cached let.
     *
     * @private
     */
    cursor: string;
    /**
     * Delayed pointer events. Used to guarantee correct ordering of over/out events.
     *
     * @private
     */
    delayedEvents: DelayedEvent[];
    /**
     * TreeSearch component that is used to hitTest stage tree.
     *
     * @private
     */
    search: TreeSearch;
    /** The renderer this interaction manager works for. */
    renderer: AbstractRenderer;
    /**
     * Should default browser actions automatically be prevented.
     * Does not apply to pointer events for backwards compatibility
     * preventDefault on pointer events stops mouse events from firing
     * Thus, for every pointer event, there will always be either a mouse of touch event alongside it.
     *
     * @default true
     */
    autoPreventDefault: boolean;
    /**
     * Maximum frequency in milliseconds at which pointer over/out states will be checked by {@link tickerUpdate}.
     *
     * @default 10
     */
    interactionFrequency: number;
    /** The mouse data. */
    mouse: InteractionData;
    /** An event data object to handle all the event tracking/dispatching. */
    eventData: InteractionEvent;
    /**
     * This property determines if mousemove and touchmove events are fired only when the cursor
     * is over the object.
     * Setting to true will make things work more in line with how the DOM version works.
     * Setting to false can make things easier for things like dragging
     * It is currently set to false as this is how PixiJS used to work. This will be set to true in
     * future versions of pixi.
     *
     * @default false
     */
    moveWhenInside: boolean;
    /**
     * Dictionary of how different cursor modes are handled. Strings are handled as CSS cursor
     * values, objects are handled as dictionaries of CSS values for interactionDOMElement,
     * and functions are called instead of changing the CSS.
     * Default CSS cursor values are provided for 'default' and 'pointer' modes.
     *
     * @member {Object.<string, Object>}
     */
    cursorStyles: Dict<string | ((mode: string) => void) | CSSStyleDeclaration>;
    /**
     * The mode of the cursor that is being used.
     * The value of this is a key from the cursorStyles dictionary.
     */
    currentCursorMode: string;
    /**
     * The current resolution / device pixel ratio.
     *
     * @default 1
     */
    resolution: number;
    /** The DOM element to bind to. */
    protected interactionDOMElement: HTMLElement;
    /** Have events been attached to the dom element? */
    protected eventsAdded: boolean;
    /** Has the system ticker been added? */
    protected tickerAdded: boolean;
    /** Is the mouse hovering over the renderer? If working in worker mouse considered to be over renderer by default. */
    protected mouseOverRenderer: boolean;
    private _useSystemTicker;
    private _deltaTime;
    private _didMove;
    /** Used as a last rendered object in case renderer doesnt have _lastObjectRendered. */
    private _tempDisplayObject;
    /**
     * An options object specifies characteristics about the event listener.
     *
     * @member {Object.<string, boolean>}
     */
    private readonly _eventListenerOptions;
    /**
     * @param {PIXI.CanvasRenderer|PIXI.Renderer} renderer - A reference to the current renderer
     * @param options - The options for the manager.
     * @param {boolean} [options.autoPreventDefault=true] - Should the manager automatically prevent default browser actions.
     * @param {number} [options.interactionFrequency=10] - Maximum frequency (ms) at pointer over/out states will be checked.
     * @param {number} [options.useSystemTicker=true] - Whether to add {@link tickerUpdate} to {@link PIXI.Ticker.system}.
     */
    constructor(renderer: AbstractRenderer, options?: InteractionManagerOptions);
    /**
     * Should the InteractionManager automatically add {@link tickerUpdate} to {@link PIXI.Ticker.system}.
     *
     * @default true
     */
    get useSystemTicker(): boolean;
    set useSystemTicker(useSystemTicker: boolean);
    /**
     * Last rendered object or temp object.
     *
     * @readonly
     * @protected
     */
    get lastObjectRendered(): DisplayObject;
    /**
     * Hit tests a point against the display tree, returning the first interactive object that is hit.
     *
     * @param globalPoint - A point to hit test with, in global space.
     * @param root - The root display object to start from. If omitted, defaults
     * to the last rendered root of the associated renderer.
     * @return - The hit display object, if any.
     */
    hitTest(globalPoint: Point, root?: DisplayObject): DisplayObject;
    /**
     * Sets the DOM element which will receive mouse/touch events. This is useful for when you have
     * other DOM elements on top of the renderers Canvas element. With this you'll be bale to delegate
     * another DOM element to receive those events.
     *
     * @param element - the DOM element which will receive mouse and touch events.
     * @param resolution - The resolution / device pixel ratio of the new element (relative to the canvas).
     */
    setTargetElement(element: HTMLElement, resolution?: number): void;
    /** Adds the ticker listener. */
    private addTickerListener;
    /** Removes the ticker listener. */
    private removeTickerListener;
    /** Registers all the DOM events. */
    private addEvents;
    /** Removes all the DOM events that were previously registered. */
    private removeEvents;
    /**
     * Updates the state of interactive objects if at least {@link interactionFrequency}
     * milliseconds have passed since the last invocation.
     *
     * Invoked by a throttled ticker update from {@link PIXI.Ticker.system}.
     *
     * @param deltaTime - time delta since the last call
     */
    tickerUpdate(deltaTime: number): void;
    /** Updates the state of interactive objects. */
    update(): void;
    /**
     * Sets the current cursor mode, handling any callbacks or CSS style changes.
     *
     * @param mode - cursor mode, a key from the cursorStyles dictionary
     */
    setCursorMode(mode: string): void;
    /**
     * Dispatches an event on the display object that was interacted with.
     *
     * @param displayObject - the display object in question
     * @param eventString - the name of the event (e.g, mousedown)
     * @param eventData - the event data object
     */
    private dispatchEvent;
    /**
     * Puts a event on a queue to be dispatched later. This is used to guarantee correct
     * ordering of over/out events.
     *
     * @param displayObject - the display object in question
     * @param eventString - the name of the event (e.g, mousedown)
     * @param eventData - the event data object
     */
    private delayDispatchEvent;
    /**
     * Maps x and y coords from a DOM object and maps them correctly to the PixiJS view. The
     * resulting value is stored in the point. This takes into account the fact that the DOM
     * element could be scaled and positioned anywhere on the screen.
     *
     * @param point - the point that the result will be stored in
     * @param x - the x coord of the position to map
     * @param y - the y coord of the position to map
     */
    mapPositionToPoint(point: IPointData, x: number, y: number): void;
    /**
     * This function is provides a neat way of crawling through the scene graph and running a
     * specified function on all interactive objects it finds. It will also take care of hit
     * testing the interactive objects and passes the hit across in the function.
     *
     * @protected
     * @param interactionEvent - event containing the point that
     *  is tested for collision
     * @param displayObject - the displayObject
     *  that will be hit test (recursively crawls its children)
     * @param func - the function that will be called on each interactive object. The
     *  interactionEvent, displayObject and hit will be passed to the function
     * @param hitTest - indicates whether we want to calculate hits
     *  or just iterate through all interactive objects
     */
    processInteractive(interactionEvent: InteractionEvent, displayObject: DisplayObject, func?: InteractionCallback, hitTest?: boolean): void;
    /**
     * Is called when the pointer button is pressed down on the renderer element
     *
     * @param originalEvent - The DOM event of a pointer button being pressed down
     */
    private onPointerDown;
    /**
     * Processes the result of the pointer down check and dispatches the event if need be
     *
     * @param interactionEvent - The interaction event wrapping the DOM event
     * @param displayObject - The display object that was tested
     * @param hit - the result of the hit test on the display object
     */
    private processPointerDown;
    /**
     * Is called when the pointer button is released on the renderer element
     *
     * @param originalEvent - The DOM event of a pointer button being released
     * @param cancelled - true if the pointer is cancelled
     * @param func - Function passed to {@link processInteractive}
     */
    private onPointerComplete;
    /**
     * Is called when the pointer button is cancelled
     *
     * @param event - The DOM event of a pointer button being released
     */
    private onPointerCancel;
    /**
     * Processes the result of the pointer cancel check and dispatches the event if need be
     *
     * @param interactionEvent - The interaction event wrapping the DOM event
     * @param displayObject - The display object that was tested
     */
    private processPointerCancel;
    /**
     * Is called when the pointer button is released on the renderer element
     *
     * @param event - The DOM event of a pointer button being released
     */
    private onPointerUp;
    /**
     * Processes the result of the pointer up check and dispatches the event if need be
     *
     * @param interactionEvent - The interaction event wrapping the DOM event
     * @param displayObject - The display object that was tested
     * @param hit - the result of the hit test on the display object
     */
    private processPointerUp;
    /**
     * Is called when the pointer moves across the renderer element
     *
     * @param originalEvent - The DOM event of a pointer moving
     */
    private onPointerMove;
    /**
     * Processes the result of the pointer move check and dispatches the event if need be
     *
     * @param interactionEvent - The interaction event wrapping the DOM event
     * @param displayObject - The display object that was tested
     * @param hit - the result of the hit test on the display object
     */
    private processPointerMove;
    /**
     * Is called when the pointer is moved out of the renderer element
     *
     * @private
     * @param {PointerEvent} originalEvent - The DOM event of a pointer being moved out
     */
    private onPointerOut;
    /**
     * Processes the result of the pointer over/out check and dispatches the event if need be.
     *
     * @param interactionEvent - The interaction event wrapping the DOM event
     * @param displayObject - The display object that was tested
     * @param hit - the result of the hit test on the display object
     */
    private processPointerOverOut;
    /**
     * Is called when the pointer is moved into the renderer element.
     *
     * @param originalEvent - The DOM event of a pointer button being moved into the renderer view.
     */
    private onPointerOver;
    /**
     * Get InteractionData for a given pointerId. Store that data as well.
     *
     * @param event - Normalized pointer event, output from normalizeToPointerData.
     * @return - Interaction data for the given pointer identifier.
     */
    private getInteractionDataForPointerId;
    /**
     * Return unused InteractionData to the pool, for a given pointerId
     *
     * @param pointerId - Identifier from a pointer event
     */
    private releaseInteractionDataForPointerId;
    /**
     * Configure an InteractionEvent to wrap a DOM PointerEvent and InteractionData
     *
     * @param interactionEvent - The event to be configured
     * @param pointerEvent - The DOM event that will be paired with the InteractionEvent
     * @param interactionData - The InteractionData that will be paired
     *        with the InteractionEvent
     * @return - the interaction event that was passed in
     */
    private configureInteractionEventForDOMEvent;
    /**
     * Ensures that the original event object contains all data that a regular pointer event would have
     *
     * @param {TouchEvent|MouseEvent|PointerEvent} event - The original event data from a touch or mouse event
     * @return - An array containing a single normalized pointer event, in the case of a pointer
     *  or mouse event, or a multiple normalized pointer events if there are multiple changed touches
     */
    private normalizeToPointerData;
    /** Destroys the interaction manager. */
    destroy(): void;
}

export declare interface InteractionManagerOptions {
    autoPreventDefault?: boolean;
    interactionFrequency?: number;
    useSystemTicker?: boolean;
}

/**
 * DisplayObjects with the {@link PIXI.interactiveTarget} mixin use this class to track interactions
 *
 * @class
 * @private
 * @memberof PIXI
 */
export declare class InteractionTrackingData {
    static FLAGS: Readonly<InteractionTrackingFlags>;
    private readonly _pointerId;
    private _flags;
    /**
     * @param {number} pointerId - Unique pointer id of the event
     * @private
     */
    constructor(pointerId: number);
    /**
     *
     * @private
     * @param {number} flag - The interaction flag to set
     * @param {boolean} yn - Should the flag be set or unset
     */
    private _doSet;
    /**
     * Unique pointer id of the event
     *
     * @readonly
     * @private
     * @member {number}
     */
    get pointerId(): number;
    /**
     * State of the tracking data, expressed as bit flags
     *
     * @private
     * @member {number}
     */
    get flags(): number;
    set flags(flags: number);
    /**
     * Is the tracked event inactive (not over or down)?
     *
     * @private
     * @member {number}
     */
    get none(): boolean;
    /**
     * Is the tracked event over the DisplayObject?
     *
     * @private
     * @member {boolean}
     */
    get over(): boolean;
    set over(yn: boolean);
    /**
     * Did the right mouse button come down in the DisplayObject?
     *
     * @private
     * @member {boolean}
     */
    get rightDown(): boolean;
    set rightDown(yn: boolean);
    /**
     * Did the left mouse button come down in the DisplayObject?
     *
     * @private
     * @member {boolean}
     */
    get leftDown(): boolean;
    set leftDown(yn: boolean);
}

export declare interface InteractionTrackingFlags {
    OVER: number;
    LEFT_DOWN: number;
    RIGHT_DOWN: number;
    NONE: number;
}

export declare type InteractivePointerEvent = PointerEvent | TouchEvent | MouseEvent;

export declare interface InteractiveTarget {
    interactive: boolean;
    interactiveChildren: boolean;
    hitArea: IHitArea | null;
    cursor: Cursor | string;
    buttonMode: boolean;
    trackedPointers: {
        [x: number]: InteractionTrackingData;
    };
    _trackedPointers: {
        [x: number]: InteractionTrackingData;
    };
}

/**
 * Default property values of interactive objects
 * Used by {@link PIXI.InteractionManager} to automatically give all DisplayObjects these properties
 *
 * @private
 * @name interactiveTarget
 * @type {Object}
 * @memberof PIXI
 * @example
 *      function MyObject() {}
 *
 *      Object.assign(
 *          DisplayObject.prototype,
 *          PIXI.interactiveTarget
 *      );
 */
export declare const interactiveTarget: InteractiveTarget;

/**
 * Strategy how to search through stage tree for interactive objects
 *
 * @memberof PIXI
 */
declare class TreeSearch {
    private readonly _tempPoint;
    constructor();
    /**
     * Recursive implementation for findHit
     *
     * @private
     * @param interactionEvent - event containing the point that
     *  is tested for collision
     * @param displayObject - the displayObject
     *  that will be hit test (recursively crawls its children)
     * @param func - the function that will be called on each interactive object. The
     *  interactionEvent, displayObject and hit will be passed to the function
     * @param hitTest - this indicates if the objects inside should be hit test against the point
     * @param interactive - Whether the displayObject is interactive
     * @return - Returns true if the displayObject hit the point
     */
    recursiveFindHit(interactionEvent: InteractionEvent, displayObject: DisplayObject, func?: InteractionCallback, hitTest?: boolean, interactive?: boolean): boolean;
    /**
     * This function is provides a neat way of crawling through the scene graph and running a
     * specified function on all interactive objects it finds. It will also take care of hit
     * testing the interactive objects and passes the hit across in the function.
     *
     * @private
     * @param interactionEvent - event containing the point that
     *  is tested for collision
     * @param displayObject - the displayObject
     *  that will be hit test (recursively crawls its children)
     * @param func - the function that will be called on each interactive object. The
     *  interactionEvent, displayObject and hit will be passed to the function
     * @param hitTest - this indicates if the objects inside should be hit test against the point
     * @return - Returns true if the displayObject hit the point
     */
    findHit(interactionEvent: InteractionEvent, displayObject: DisplayObject, func?: InteractionCallback, hitTest?: boolean): void;
}

export { }
