/**
 * 2D Renderer Plugin for ECSpresso
 *
 * An opt-in PixiJS-based 2D rendering plugin that automates scene graph wiring.
 * Import from 'ecspresso/plugins/rendering/renderer2D'
 *
 * This plugin includes transform propagation automatically.
 */
import type { Application, ApplicationOptions, Container, Sprite, Graphics } from 'pixi.js';
import { type Plugin } from 'ecspresso';
import type { ComponentsConfig, EmptyConfig, EventsConfig, ResourcesConfig, WorldConfig } from '../../type-utils';
import { type LocalTransform, type WorldTransform, type TransformComponentTypes, type TransformPluginOptions } from 'ecspresso/plugins/spatial/transform';
import { type BoundsRect } from 'ecspresso/plugins/spatial/bounds';
import type { CameraResourceTypes } from 'ecspresso/plugins/spatial/camera';
export type { LocalTransform, WorldTransform, TransformComponentTypes };
export type { BoundsRect };
export { createTransform, createLocalTransform, createWorldTransform, DEFAULT_LOCAL_TRANSFORM, DEFAULT_WORLD_TRANSFORM } from 'ecspresso/plugins/spatial/transform';
/**
 * Visibility and alpha component
 */
export interface Visible {
    visible: boolean;
    alpha?: number;
}
/**
 * Aggregate component types for the 2D renderer plugin.
 * Included automatically via `.withPlugin(createRenderer2DPlugin({ ... }))`.
 *
 * @example
 * ```typescript
 * const ecs = ECSpresso.create()
 *   .withPlugin(createRenderer2DPlugin({ ... }))
 *   .withComponentTypes<{ velocity: { x: number; y: number }; player: true }>()
 *   .build();
 * ```
 */
export interface Renderer2DComponentTypes extends TransformComponentTypes {
    sprite: Sprite;
    graphics: Graphics;
    container: Container;
    visible: Visible;
    /** Assigns the entity to a named render layer for z-ordering */
    renderLayer: string;
}
/**
 * Events emitted by the 2D renderer plugin
 */
export interface Renderer2DEventTypes {
    hierarchyChanged: {
        entityId: number;
        oldParent: number | null;
        newParent: number | null;
    };
}
/**
 * Resources provided by the 2D renderer plugin
 */
export interface Renderer2DResourceTypes {
    pixiApp: Application;
    rootContainer: Container;
    /** Screen bounds derived from PixiJS screen dimensions, updated on resize */
    bounds: BoundsRect;
}
export type ScaleMode = 'fit' | 'cover' | 'stretch';
export interface ScreenScaleOptions {
    readonly width: number;
    readonly height: number;
    readonly mode?: ScaleMode;
}
export interface ViewportScale {
    scaleX: number;
    scaleY: number;
    offsetX: number;
    offsetY: number;
    physicalWidth: number;
    physicalHeight: number;
    /** Current scale mode. Mutable — call `reapplyViewportScale(pixiApp)` after changing to re-apply immediately. */
    mode: ScaleMode;
    readonly designWidth: number;
    readonly designHeight: number;
}
export interface ViewportScaleResourceTypes {
    viewportScale: ViewportScale;
}
/**
 * Common options shared between both initialization modes
 */
interface Renderer2DPluginCommonOptions<G extends string = 'renderer2d'> {
    /** Optional custom root container (defaults to app.stage) */
    rootContainer?: Container;
    /** System group name (default: 'renderer2d') */
    systemGroup?: G;
    /** Priority for render sync system (default: 500) */
    renderSyncPriority?: number;
    /** Options for the included transform plugin */
    transform?: TransformPluginOptions;
    /** When true, wires up pixiApp.ticker to drive ecs.update() automatically (default: true) */
    startLoop?: boolean;
    /** Ordered render layer names (back-to-front). Entities with a renderLayer component are placed in the corresponding container. */
    renderLayers?: string[];
    /** Render layers that should not be affected by camera transforms.
     *  These layers are placed outside rootContainer so camera zoom/pan/rotation does not apply.
     *  Only relevant when `camera: true`. Layer names listed here must also appear in `renderLayers`. */
    screenSpaceLayers?: string[];
    /** Automatically apply cameraState resource to rootContainer each frame.
     *  Requires the camera plugin to be installed. (default: false) */
    camera?: boolean;
    /** Enforce a logical design resolution with automatic aspect-ratio-aware scaling.
     *  When set, systems work in design-resolution coordinate space. */
    screenScale?: ScreenScaleOptions;
}
/**
 * Options when providing a pre-initialized PixiJS Application
 */
export interface Renderer2DPluginAppOptions<G extends string = 'renderer2d'> extends Renderer2DPluginCommonOptions<G> {
    /** The PixiJS Application instance (already initialized) */
    app: Application;
    pixiInit?: never;
    container?: never;
    background?: never;
    width?: never;
    height?: never;
}
/**
 * Options when letting the plugin create and manage the PixiJS Application
 */
export interface Renderer2DPluginManagedOptions<G extends string = 'renderer2d'> extends Renderer2DPluginCommonOptions<G> {
    app?: never;
    /** Container element to append the canvas to (or CSS selector string). Defaults to `document.body`.
     *  The canvas also auto-resizes to this element unless `width`/`height` are set or `pixiInit.resizeTo` is set explicitly. */
    container?: HTMLElement | string;
    /** Canvas background color. */
    background?: ApplicationOptions['background'];
    /** Fixed canvas width. When set (with `height`), the canvas is fixed-size and the auto-resize default is suppressed. */
    width?: ApplicationOptions['width'];
    /** Fixed canvas height. When set (with `width`), the canvas is fixed-size and the auto-resize default is suppressed. */
    height?: ApplicationOptions['height'];
    /** Escape hatch for raw PixiJS ApplicationOptions not otherwise exposed at the top level.
     *  Top-level fields (`background`, `width`, `height`) take precedence when both are set. */
    pixiInit?: Partial<ApplicationOptions>;
}
/**
 * Configuration options for the 2D renderer plugin.
 *
 * Supports two modes:
 * 1. **Pre-initialized**: Pass an already-initialized Application via `app`
 * 2. **Managed**: Omit `app` and the plugin creates the Application during `ecs.initialize()`.
 *    The canvas is appended to `container` (defaults to `document.body`) and auto-resizes to
 *    match it. Pass `pixiInit: { width, height }` for a fixed-size canvas instead.
 *
 * This plugin includes transform propagation automatically - no need to add createTransformPlugin() separately.
 *
 * @example Pre-initialized mode (full control)
 * ```typescript
 * const app = new Application();
 * await app.init({ resizeTo: window });
 * const ecs = ECSpresso.create()
 *   .withPlugin(createRenderer2DPlugin({ app }))
 *   .withComponentTypes<{ player: true }>()
 *   .build();
 * ```
 *
 * @example Managed mode (convenience)
 * ```typescript
 * const ecs = ECSpresso.create()
 *   .withPlugin(createRenderer2DPlugin({
 *     background: '#1099bb',
 *   }))
 *   .withComponentTypes<{ player: true }>()
 *   .build();
 * await ecs.initialize(); // Application created here
 * ```
 */
export type Renderer2DPluginOptions<G extends string = 'renderer2d'> = Renderer2DPluginAppOptions<G> | Renderer2DPluginManagedOptions<G>;
interface PositionOption {
    x?: number;
    y?: number;
}
interface TransformOptions {
    rotation?: number;
    scale?: number | {
        x: number;
        y: number;
    };
    visible?: boolean;
    alpha?: number;
}
/**
 * Create components for a sprite entity.
 * Returns an object suitable for spreading into spawn().
 *
 * @example
 * ```typescript
 * const player = ecs.spawn({
 *   ...createSpriteComponents(new Sprite(texture), { x: 100, y: 100 }),
 *   velocity: { x: 0, y: 0 },
 * });
 * ```
 */
export declare function createSpriteComponents(sprite: Sprite, position?: PositionOption, options?: TransformOptions & {
    anchor?: {
        x: number;
        y: number;
    };
}): Pick<Renderer2DComponentTypes, 'sprite' | 'localTransform' | 'worldTransform' | 'visible'>;
/**
 * Create components for a graphics entity.
 * Returns an object suitable for spreading into spawn().
 *
 * @example
 * ```typescript
 * const rect = ecs.spawn({
 *   ...createGraphicsComponents(graphics, { x: 50, y: 50 }),
 * });
 * ```
 */
export declare function createGraphicsComponents(graphics: Graphics, position?: PositionOption, options?: TransformOptions): Pick<Renderer2DComponentTypes, 'graphics' | 'localTransform' | 'worldTransform' | 'visible'>;
/**
 * Create components for a container entity.
 * Returns an object suitable for spreading into spawn().
 *
 * @example
 * ```typescript
 * const group = ecs.spawn({
 *   ...createContainerComponents(new Container(), { x: 0, y: 0 }),
 * });
 * ```
 */
export declare function createContainerComponents(container: Container, position?: PositionOption, options?: TransformOptions): Pick<Renderer2DComponentTypes, 'container' | 'localTransform' | 'worldTransform' | 'visible'>;
export declare function computeViewportScale(physicalW: number, physicalH: number, designW: number, designH: number, mode: ScaleMode): ViewportScale;
/**
 * Convert physical canvas pixel coordinates to design-resolution (logical) coordinates.
 * Compose with camera `screenToWorld()` for full physical→world conversion.
 */
export declare function physicalToLogical(physicalX: number, physicalY: number, viewport: ViewportScale): {
    x: number;
    y: number;
};
/**
 * Convert a DOM pointer event's client coordinates to design-resolution (logical) coordinates.
 * Handles canvas offset, CSS-pixel to physical-pixel scaling, and viewport letterbox/crop offsets.
 * Suitable for wiring into the input plugin's `coordinateTransform` option.
 */
export declare function clientToLogical(clientX: number, clientY: number, canvas: HTMLCanvasElement, viewport: ViewportScale): {
    x: number;
    y: number;
};
/**
 * Re-apply the current viewport scale using the latest `mode` from the `viewportScale` resource.
 * Call after mutating `viewportScale.mode` to take effect immediately without waiting for a window resize.
 */
export declare function reapplyViewportScale(pixiApp: Application): void;
/**
 * Create a 2D rendering plugin for ECSpresso.
 *
 * This plugin provides:
 * - Transform propagation (localTransform -> worldTransform)
 * - Render sync system (updates PixiJS objects from ECS components)
 * - Scene graph management (mirrors ECS hierarchy in PixiJS scene graph)
 *
 * @example Pre-initialized mode
 * ```typescript
 * const app = new Application();
 * await app.init({ resizeTo: window });
 *
 * const ecs = ECSpresso.create<GameComponents, {}, {}>()
 *   .withPlugin(createRenderer2DPlugin({ app }))
 *   .build();
 * ```
 *
 * @example Managed mode
 * ```typescript
 * const ecs = ECSpresso.create<GameComponents, {}, {}>()
 *   .withPlugin(createRenderer2DPlugin({
 *     background: '#1099bb',
 *   }))
 *   .build();
 * await ecs.initialize();
 * ```
 */
type Renderer2DLabels = 'renderer2d-sync' | 'renderer2d-scene-graph' | 'renderer2d-camera-sync' | 'transform-propagation';
type Renderer2DReactiveQueryNames = 'renderer2d-sprites' | 'renderer2d-graphics' | 'renderer2d-containers';
type Renderer2DWorldConfig<R extends WorldConfig['resources'] = Renderer2DResourceTypes> = ComponentsConfig<Renderer2DComponentTypes> & EventsConfig<Renderer2DEventTypes> & ResourcesConfig<R>;
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G> & {
    screenScale: ScreenScaleOptions;
    camera: true;
}): Plugin<Renderer2DWorldConfig<Renderer2DResourceTypes & ViewportScaleResourceTypes & CameraResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G> & {
    screenScale: ScreenScaleOptions;
}): Plugin<Renderer2DWorldConfig<Renderer2DResourceTypes & ViewportScaleResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G> & {
    camera: true;
}): Plugin<Renderer2DWorldConfig<Renderer2DResourceTypes & CameraResourceTypes>, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
export declare function createRenderer2DPlugin<G extends string = 'renderer2d'>(options: Renderer2DPluginOptions<G>): Plugin<Renderer2DWorldConfig, EmptyConfig, Renderer2DLabels, G, never, Renderer2DReactiveQueryNames>;
