/**
 * Particle System Plugin for ECSpresso
 *
 * High-performance particle system where particles live outside the ECS in
 * pre-allocated pools. Renders via PixiJS v8's ParticleContainer + Particle API.
 * Renderer2D is a required dependency.
 *
 * Follows the established plugin pattern: immutable shared config
 * (ParticleEffectConfig) + mutable per-entity state (ParticleEmitter) component,
 * side-storage Map for PixiJS objects, kit pattern for typed helpers.
 */
import { type BasePluginOptions } from 'ecspresso';
import type { BaseWorld } from 'ecspresso';
import type { ComponentsConfig } from '../../type-utils';
import type { TransformComponentTypes } from 'ecspresso/plugins/spatial/transform';
/** BaseWorld narrowed to particle components for typed access in helpers. */
type ParticleWorld = BaseWorld<ParticleComponentTypes>;
/** Fixed value or random range [min, max] */
export type ParticleValue = number | readonly [number, number];
/** Emission geometry */
export type EmissionShape = 'point' | 'circle';
/** Blend modes for particle rendering */
export type ParticleBlendMode = 'normal' | 'add' | 'multiply' | 'screen';
/**
 * User-facing config input for defining a particle effect.
 * All properties optional except maxParticles and texture.
 */
export interface ParticleEffectInput {
    /** Pool size — maximum simultaneous particles */
    maxParticles: number;
    /** PixiJS Texture for particles */
    texture: unknown;
    /** Particles per second (0 = burst-only, default: 10) */
    spawnRate?: number;
    /** Particles per burst (default: 0) */
    burstCount?: number;
    /** Emitter lifetime in seconds (-1 = infinite, default: -1) */
    duration?: number;
    /** Per-particle lifetime in seconds (default: 1) */
    lifetime?: ParticleValue;
    /** Initial speed in pixels/second (default: 100) */
    speed?: ParticleValue;
    /** Emission direction in radians (default: [0, 2*PI]) */
    angle?: ParticleValue;
    /** Spawn geometry (default: 'point') */
    emissionShape?: EmissionShape;
    /** Radius for 'circle' shape (default: 0) */
    emissionRadius?: number;
    /** Acceleration in pixels/second^2 (default: {x: 0, y: 0}) */
    gravity?: {
        readonly x: number;
        readonly y: number;
    };
    /** Initial scale (default: 1) */
    startSize?: ParticleValue;
    /** Final scale (default: same as startSize) */
    endSize?: ParticleValue;
    /** Initial opacity (default: 1) */
    startAlpha?: ParticleValue;
    /** Final opacity (default: 0) */
    endAlpha?: ParticleValue;
    /** Initial hex color (default: 0xffffff) */
    startTint?: number;
    /** Final hex color (default: same as startTint) */
    endTint?: number;
    /** Initial rotation in radians (default: 0) */
    startRotation?: ParticleValue;
    /** Rotation velocity in rad/s (default: 0) */
    rotationSpeed?: ParticleValue;
    /** Blend mode (default: 'normal') */
    blendMode?: ParticleBlendMode;
    /** Particles in world coordinates (default: true) */
    worldSpace?: boolean;
}
/**
 * Frozen, fully-resolved particle effect config.
 * Output of defineParticleEffect.
 */
export interface ParticleEffectConfig {
    readonly maxParticles: number;
    readonly texture: unknown;
    readonly spawnRate: number;
    readonly burstCount: number;
    readonly duration: number;
    readonly lifetime: ParticleValue;
    readonly speed: ParticleValue;
    readonly angle: ParticleValue;
    readonly emissionShape: EmissionShape;
    readonly emissionRadius: number;
    readonly gravity: {
        readonly x: number;
        readonly y: number;
    };
    readonly startSize: ParticleValue;
    readonly endSize: ParticleValue;
    readonly startAlpha: ParticleValue;
    readonly endAlpha: ParticleValue;
    readonly startTint: number;
    readonly endTint: number;
    readonly startRotation: ParticleValue;
    readonly rotationSpeed: ParticleValue;
    readonly blendMode: ParticleBlendMode;
    readonly worldSpace: boolean;
}
/**
 * Mutable per-particle state. Pre-allocated, never GC'd.
 */
export interface ParticleState {
    active: boolean;
    x: number;
    y: number;
    vx: number;
    vy: number;
    life: number;
    maxLife: number;
    size: number;
    startSize: number;
    endSize: number;
    alpha: number;
    startAlpha: number;
    endAlpha: number;
    tint: number;
    rotation: number;
    rotationSpeed: number;
}
/**
 * Per-entity emitter state stored as an ECS component.
 */
export interface ParticleEmitter {
    readonly config: ParticleEffectConfig;
    activeCount: number;
    spawnAccumulator: number;
    elapsed: number;
    playing: boolean;
    pendingBurst: number;
    finished: boolean;
    onComplete?: (data: ParticleEmitterEventData) => void;
}
/**
 * Component types provided by the particle plugin.
 */
export interface ParticleComponentTypes {
    particleEmitter: ParticleEmitter;
}
/**
 * Data published when an emitter completes.
 */
export interface ParticleEmitterEventData {
    entityId: number;
}
export interface ParticlePluginOptions<G extends string = 'particles'> extends BasePluginOptions<G> {
}
/**
 * Sample a ParticleValue: returns fixed value or random within [min, max].
 */
export declare function sampleRange(value: ParticleValue): number;
/**
 * Linear interpolation between two hex colors (RGB channels).
 */
export declare function lerpTint(start: number, end: number, t: number): number;
/**
 * Define a particle effect config with defaults applied and frozen.
 */
export declare function defineParticleEffect(input: ParticleEffectInput): ParticleEffectConfig;
/**
 * Create a particleEmitter component suitable for spreading into spawn().
 */
export declare function createParticleEmitter(config: ParticleEffectConfig, options?: {
    playing?: boolean;
    onComplete?: (data: ParticleEmitterEventData) => void;
}): Pick<ParticleComponentTypes, 'particleEmitter'>;
/**
 * Queue a burst of particles on an emitter.
 * Returns false if entity has no particleEmitter component.
 */
export declare function burstParticles(ecs: ParticleWorld, entityId: number, count?: number): boolean;
/**
 * Stop an emitter from spawning new particles.
 * Existing particles continue their lifecycle.
 */
export declare function stopEmitter(ecs: ParticleWorld, entityId: number): boolean;
/**
 * Resume a stopped emitter.
 */
export declare function resumeEmitter(ecs: ParticleWorld, entityId: number): boolean;
/**
 * Runtime data stored outside the ECS, keyed by entity ID.
 */
export interface EmitterRuntimeData {
    particles: ParticleState[];
    pixiContainer: unknown;
    pixiParticles: unknown[];
}
export declare const particlePresets: {
    readonly explosion: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
    readonly smoke: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
    readonly fire: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
    readonly sparkle: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
    readonly trail: (texture: unknown, overrides?: Partial<ParticleEffectInput>) => ParticleEffectConfig;
};
type ParticleLabels = 'particle-update' | 'particle-render-sync';
type ParticleRequires = ComponentsConfig<TransformComponentTypes & {
    renderLayer: string;
}>;
/**
 * Create a particle system plugin for ECSpresso.
 *
 * Provides:
 * - Pre-allocated particle pools outside the entity system
 * - Continuous and burst emission modes
 * - Velocity, gravity, lifetime, interpolation (size, alpha, tint, rotation)
 * - World-space and local-space particle emission
 * - PixiJS ParticleContainer rendering (via renderer2D dependency)
 * - Presets for common effects (explosion, smoke, fire, sparkle, trail)
 *
 * Renderer2D is a required dependency.
 */
export declare function createParticlePlugin<G extends string = 'particles'>(options?: ParticlePluginOptions<G>): import("ecspresso").Plugin<import("ecspresso").WithComponents<import("ecspresso").EmptyConfig, ParticleComponentTypes>, ParticleRequires, ParticleLabels, G, never, "particle-emitters">;
/**
 * Get the runtime data for an emitter entity.
 * Useful for tests and advanced usage.
 * @internal Exported for testing only.
 */
export declare function getEmitterData(emitterDataMap: Map<number, EmitterRuntimeData>, entityId: number): EmitterRuntimeData | undefined;
export {};
