import { type InstructionSet } from '../../rendering/renderers/shared/instructions/InstructionSet';
import { type Renderer } from '../../rendering/renderers/types';
import { type Bounds } from '../container/bounds/Bounds';
import { Container } from '../container/Container';
/**
 * Options for configuring a RenderLayer. A RenderLayer allows control over rendering order
 * independent of the scene graph hierarchy.
 * @example
 * ```ts
 * // Basic layer with automatic sorting
 * const layer = new RenderLayer({
 *     sortableChildren: true
 * });
 *
 * // Layer with custom sort function
 * const customLayer = new RenderLayer({
 *     sortableChildren: true,
 *     sortFunction: (a, b) => {
 *         // Sort by y position
 *         return a.position.y - b.position.y;
 *     }
 * });
 *
 * // Add objects to layer while maintaining scene graph parent
 * const sprite = new Sprite(texture);
 * container.addChild(sprite);      // Add to scene graph
 * layer.attach(sprite);            // Add to render layer
 *
 * // Manual sorting when needed
 * const manualLayer = new RenderLayer({
 *     sortableChildren: false
 * });
 * manualLayer.attach(sprite1, sprite2);
 * manualLayer.sortRenderLayerChildren(); // Sort manually
 * ```
 * @category scene
 * @standard
 */
export interface RenderLayerOptions {
    /**
     * If true, the layer's children will be sorted by zIndex before rendering.
     * If false, you can manually sort the children using sortRenderLayerChildren when needed.
     * @default false
     * @example
     * ```ts
     * const layer = new RenderLayer({
     *     sortableChildren: true // Automatically sorts children by zIndex
     * });
     * ```
     * @see {@link RenderLayer#sortRenderLayerChildren} For manual sorting
     * @see {@link RenderLayer#sortFunction} For customizing the sort logic
     * @see {@link Container#zIndex} For the default sort property
     */
    sortableChildren?: boolean;
    /**
     * Custom sort function to sort layer children. Default sorts by zIndex.
     * @param a - First container to compare
     * @param b - Second container to compare
     * @returns Negative if a should render before b, positive if b should render before a
     * @example
     * ```ts
     * const layer = new RenderLayer({
     *     sortFunction: (a, b) => {
     *         // Sort by y position
     *         return a.position.y - b.position.y;
     *     }
     * });
     * ```
     * @see {@link RenderLayer#sortableChildren} For enabling automatic sorting
     * @see {@link RenderLayer#sortRenderLayerChildren} For manual sorting
     * @see {@link Container#zIndex} For the default sort property
     * @default (a, b) => a.zIndex - b.zIndex
     */
    sortFunction?: (a: Container, b: Container) => number;
}
/**
 * The RenderLayer API provides a way to control the rendering order of objects independently
 * of their logical parent-child relationships in the scene graph.
 * This allows developers to decouple how objects are transformed
 * (via their logical parent) from how they are rendered on the screen.
 *
 * ### Key Concepts
 *
 * #### RenderLayers Control Rendering Order:
 * - RenderLayers define where in the render stack objects are drawn,
 * but they do not affect an object's transformations (e.g., position, scale, rotation) or logical hierarchy.
 * - RenderLayers can be added anywhere in the scene graph.
 *
 * #### Logical Parenting Remains Unchanged:
 * - Objects still have a logical parent for transformations via addChild.
 * - Assigning an object to a layer does not reparent it.
 *
 * #### Explicit Control:
 * - Developers assign objects to layers using renderLayer.add and remove them using renderLayer.remove.
 * ---
 * ### API Details
 *
 * #### 1. Creating a RenderLayer
 * A RenderLayer is a lightweight object responsible for controlling render order.
 * It has no children or transformations of its own
 * but can be inserted anywhere in the scene graph to define its render position.
 * ```js
 * const layer = new RenderLayer();
 * app.stage.addChild(layer); // Insert the layer into the scene graph
 * ```
 *
 * #### 2. Adding Objects to a Layer
 * Use renderLayer.add to assign an object to a layer.
 * This overrides the object's default render order defined by its logical parent.
 * ```js
 * const rect = new Graphics();
 * container.addChild(rect);    // Add to logical parent
 * layer.attach(rect);      // Control render order via the layer
 * ```
 *
 * #### 3. Removing Objects from a Layer
 * To stop an object from being rendered in the layer, use remove.
 * ```js
 * layer.remove(rect); // Stop rendering rect via the layer
 * ```
 * When an object is removed from its logical parent (removeChild), it is automatically removed from the layer.
 *
 * #### 4. Re-Adding Objects to Layers
 * If an object is re-added to a logical parent, it does not automatically reassign itself to the layer.
 * Developers must explicitly reassign it.
 * ```js
 * container.addChild(rect);    // Logical parent
 * layer.attach(rect);      // Explicitly reassign to the layer
 * ```
 *
 * #### 5. Layer Position in Scene Graph
 * A layer's position in the scene graph determines its render priority relative to other layers and objects.
 * Layers can be inserted anywhere in the scene graph.
 * ```js
 * const backgroundLayer = new RenderLayer();
 * const uiLayer = new RenderLayer();
 *
 * app.stage.addChild(backgroundLayer);
 * app.stage.addChild(world);
 * app.stage.addChild(uiLayer);
 * ```
 * This is a new API and therefore considered experimental at this stage.
 * While the core is pretty robust, there are still a few tricky issues we need to tackle.
 * However, even with the known issues below, we believe this API is incredibly useful!
 *
 * Known issues:
 *  - Interaction may not work as expected since hit testing does not account for the visual render order created by layers.
 *    For example, if an object is visually moved to the front via a layer, hit testing will still use its original position.
 *  - RenderLayers and their children must all belong to the same renderGroup to work correctly
 * @category scene
 * @class
 * @extends null
 * @standard
 */
export declare class RenderLayer extends Container {
    /**
     * Default options for RenderLayer instances. These options control the sorting behavior
     * of objects within the render layer.
     * @example
     * ```ts
     * // Create a custom render layer with modified default options
     * RenderLayer.defaultOptions = {
     *     sortableChildren: true,
     *     sortFunction: (a, b) => a.y - b.y // Sort by vertical position
     * };
     *
     * // All new render layers will use these defaults
     * const layer1 = new RenderLayer();
     * // layer1 will have sortableChildren = true
     * ```
     * @property {boolean} sortableChildren -
     * @property {Function} sortFunction -
     * @see {@link RenderLayer} For the main render layer class
     * @see {@link Container#zIndex} For the default sort property
     * @see {@link RenderLayer#sortRenderLayerChildren} For manual sorting
     */
    static defaultOptions: RenderLayerOptions;
    /** Function used to sort layer children if sortableChildren is true */
    sortFunction: (a: Container, b: Container) => number;
    /**
     * The list of objects that this layer is responsible for rendering. Objects in this list maintain
     * their original parent in the scene graph but are rendered as part of this layer.
     * @example
     * ```ts
     * const layer = new RenderLayer();
     * const sprite = new Sprite(texture);
     *
     * // Add sprite to scene graph for transforms
     * container.addChild(sprite);
     *
     * // Add to layer for render order control
     * layer.attach(sprite);
     * console.log(layer.renderLayerChildren.length); // 1
     *
     * // Access objects in the layer
     * layer.renderLayerChildren.forEach(child => {
     *     console.log('Layer child:', child);
     * });
     *
     * // Check if object is in layer
     * const isInLayer = layer.renderLayerChildren.includes(sprite);
     *
     * // Clear all objects from layer
     * layer.detachAll();
     * console.log(layer.renderLayerChildren.length); // 0
     * ```
     * @readonly
     * @see {@link RenderLayer#attach} For adding objects to the layer
     * @see {@link RenderLayer#detach} For removing objects from the layer
     * @see {@link RenderLayer#detachAll} For removing all objects from the layer
     */
    renderLayerChildren: Container[];
    /** @internal */
    parent: Container | null;
    /** @internal */
    didChange: boolean;
    /** @internal */
    _updateFlags: number;
    /** @internal */
    parentRenderLayer: null;
    /** @internal */
    destroyed: boolean;
    /** @internal */
    layerParentId: string;
    /**
     * If true, the layer's children will be sorted by zIndex before rendering.
     * If false, you can manually sort the children using sortRenderLayerChildren when needed.
     * @default false
     * @example
     * ```ts
     * const layer = new RenderLayer({
     *     sortableChildren: true // Automatically sorts children by zIndex
     * });
     * ```
     * @see {@link RenderLayer#sortRenderLayerChildren} For manual sorting
     * @see {@link RenderLayer#sortFunction} For customizing the sort logic
     * @see {@link Container#zIndex} For the default sort property
     */
    sortableChildren: boolean;
    /**
     * Creates a new RenderLayer instance
     * @param options - Configuration options for the RenderLayer
     * @param {boolean} [options.sortableChildren=false] - If true, layer children will be automatically sorted each render
     * @param {Function} [options.sortFunction] - Custom function to sort layer children. Default sorts by zIndex
     */
    constructor(options?: RenderLayerOptions);
    /**
     * Adds one or more Containers to this render layer. The Containers will be rendered as part of this layer
     * while maintaining their original parent in the scene graph.
     *
     * If the Container already belongs to a layer, it will be removed from the old layer before being added to this one.
     * @example
     * ```ts
     * const layer = new RenderLayer();
     * const container = new Container();
     * const sprite1 = new Sprite(texture1);
     * const sprite2 = new Sprite(texture2);
     *
     * // Add sprites to scene graph for transforms
     * container.addChild(sprite1, sprite2);
     *
     * // Add sprites to layer for render order control
     * layer.attach(sprite1, sprite2);
     *
     * // Add single sprite with type checking
     * const typedSprite = layer.attach<Sprite>(new Sprite(texture3));
     * typedSprite.tint = 'red';
     *
     * // Automatically removes from previous layer if needed
     * const otherLayer = new RenderLayer();
     * otherLayer.attach(sprite1); // Removes from previous layer
     * ```
     * @param children - The Container(s) to add to this layer. Can be any Container or array of Containers.
     * @returns The first child that was added, for method chaining
     * @see {@link RenderLayer#detach} For removing objects from the layer
     * @see {@link RenderLayer#detachAll} For removing all objects from the layer
     * @see {@link Container#addChild} For adding to scene graph hierarchy
     */
    attach<U extends Container[]>(...children: U): U[0];
    /**
     * Removes one or more Containers from this render layer. The Containers will maintain their
     * original parent in the scene graph but will no longer be rendered as part of this layer.
     * @example
     * ```ts
     * const layer = new RenderLayer();
     * const container = new Container();
     * const sprite1 = new Sprite(texture1);
     * const sprite2 = new Sprite(texture2);
     *
     * // Add sprites to scene graph and layer
     * container.addChild(sprite1, sprite2);
     * layer.attach(sprite1, sprite2);
     *
     * // Remove single sprite from layer
     * layer.detach(sprite1);
     * // sprite1 is still child of container but not rendered in layer
     *
     * // Remove multiple sprites at once
     * const otherLayer = new RenderLayer();
     * otherLayer.attach(sprite3, sprite4);
     * otherLayer.detach(sprite3, sprite4);
     *
     * // Type-safe detachment
     * const typedSprite = layer.detach<Sprite>(spriteInLayer);
     * typedSprite.texture = newTexture; // TypeScript knows this is a Sprite
     * ```
     * @param children - The Container(s) to remove from this layer
     * @returns The first child that was removed, for method chaining
     * @see {@link RenderLayer#attach} For adding objects to the layer
     * @see {@link RenderLayer#detachAll} For removing all objects from the layer
     * @see {@link Container#removeChild} For removing from scene graph hierarchy
     */
    detach<U extends Container[]>(...children: U): U[0];
    /**
     * Removes all objects from this render layer. Objects will maintain their
     * original parent in the scene graph but will no longer be rendered as part of this layer.
     * @example
     * ```ts
     * const layer = new RenderLayer();
     * const container = new Container();
     *
     * // Add multiple sprites to scene graph and layer
     * const sprites = [
     *     new Sprite(texture1),
     *     new Sprite(texture2),
     *     new Sprite(texture3)
     * ];
     *
     * container.addChild(...sprites);  // Add to scene graph
     * layer.attach(...sprites);       // Add to render layer
     *
     * // Later, remove all sprites from layer at once
     * layer.detachAll();
     * console.log(layer.renderLayerChildren.length); // 0
     * console.log(container.children.length);        // 3 (still in scene graph)
     * ```
     * @returns The RenderLayer instance for method chaining
     * @see {@link RenderLayer#attach} For adding objects to the layer
     * @see {@link RenderLayer#detach} For removing individual objects
     * @see {@link Container#removeChildren} For removing from scene graph
     */
    detachAll(): void;
    /**
     * Collects renderables for this layer and its children.
     * This method is called by the renderer to gather all objects that should be rendered in this layer.
     * @param instructionSet - The set of instructions to collect renderables into.
     * @param renderer - The renderer that is collecting renderables.
     * @param _currentLayer - The current render layer being processed.
     * @internal
     */
    collectRenderables(instructionSet: InstructionSet, renderer: Renderer, _currentLayer: RenderLayer): void;
    /**
     * Sort the layer's children using the defined sort function. This method allows manual sorting
     * of layer children and is automatically called during rendering if sortableChildren is true.
     * @example
     * ```ts
     * const layer = new RenderLayer();
     *
     * // Add multiple sprites at different depths
     * const sprite1 = new Sprite(texture);
     * const sprite2 = new Sprite(texture);
     * const sprite3 = new Sprite(texture);
     *
     * sprite1.zIndex = 3;
     * sprite2.zIndex = 1;
     * sprite3.zIndex = 2;
     *
     * layer.attach(sprite1, sprite2, sprite3);
     *
     * // Manual sorting with default zIndex sort
     * layer.sortRenderLayerChildren();
     * // Order is now: sprite2 (1), sprite3 (2), sprite1 (3)
     *
     * // Custom sort by y position
     * layer.sortFunction = (a, b) => a.y - b.y;
     * layer.sortRenderLayerChildren();
     *
     * // Automatic sorting
     * layer.sortableChildren = true; // Will sort each render
     * ```
     * @returns The RenderLayer instance for method chaining
     * @see {@link RenderLayer#sortableChildren} For enabling automatic sorting
     * @see {@link RenderLayer#sortFunction} For customizing the sort logic
     */
    sortRenderLayerChildren(): void;
    /**
     * Recursively calculates the global bounds of this RenderLayer and its children.
     * @param factorRenderLayers
     * @param bounds
     * @param _currentLayer
     * @internal
     */
    _getGlobalBoundsRecursive(factorRenderLayers: boolean, bounds: Bounds, _currentLayer: RenderLayer): void;
    /**
     * @inheritdoc
     * @internal
     */
    getFastGlobalBounds(factorRenderLayers?: boolean, bounds?: Bounds): Bounds;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error. Please use `RenderLayer.attach()` instead.
     * @param {...any} _children
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    addChild<U extends Container[]>(..._children: U): never;
    /**
     * This method is not available in RenderLayer.
     * Calling this method will throw an error. Please use `RenderLayer.detach()` instead.
     * @param {...any} _children
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    removeChild<U extends Container[]>(..._children: U): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error. Please use `RenderLayer.detach()` instead.
     * @param {number} [_beginIndex]
     * @param {number} [_endIndex]
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    removeChildren(_beginIndex?: number, _endIndex?: number): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param {number} _index
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    removeChildAt(_index: number): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param {number} _index
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    getChildAt(_index: number): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param {Container} _child
     * @param {number} _index
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    setChildIndex(_child: Container, _index: number): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param {Container} _child
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    getChildIndex(_child: Container): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param {Container} _child
     * @param {number} _index
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    addChildAt<U extends Container>(_child: U, _index: number): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param {Container} _child
     * @param {Container} _child2
     * @ignore
     */
    swapChildren<U extends Container>(_child: U, _child2: U): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param _child - The child to reparent
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    reparentChild(..._child: Container[]): never;
    /**
     * This method is not available in RenderLayer.
     *
     * Calling this method will throw an error.
     * @param _child - The child to reparent
     * @param _index - The index to reparent the child to
     * @throws {Error} Always throws an error as this method is not available.
     * @ignore
     */
    reparentChildAt(_child: Container, _index: number): never;
}
