import { BufferGeometry, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, SpriteMaterial, Vector3 } from "three";
import type { Behavior, Particle } from "three.quarks";
import { ParticleSystem as _ParticleSystem } from "three.quarks";
import { Context } from "../../engine/engine_setup.js";
import { Behaviour, GameObject } from "../Component.js";
import { ColorBySpeedModule, ColorOverLifetimeModule, EmissionModule, InheritVelocityModule, type IParticleSystem, LimitVelocityOverLifetimeModule, MainModule, NoiseModule, ParticleSystemRenderMode, RotationBySpeedModule, RotationOverLifetimeModule, ShapeModule, SizeBySpeedModule, SizeOverLifetimeModule, TextureSheetAnimationModule, TrailModule, VelocityOverLifetimeModule } from "./ParticleSystemModules.js";
export type { Particle as QParticle, Behavior as QParticleBehaviour, TrailParticle as QTrailParticle } from "three.quarks";
/**
 * Defines when a sub-emitter spawns particles relative to the parent particle's lifecycle.
 * Used to create complex effects like explosions on impact or trails following particles.
 */
export declare enum SubEmitterType {
    /** Sub-emitter triggers when the parent particle is born */
    Birth = 0,
    /** Sub-emitter triggers when the parent particle collides */
    Collision = 1,
    /** Sub-emitter triggers when the parent particle dies */
    Death = 2,
    /** Sub-emitter triggers when the parent particle enters a trigger zone */
    Trigger = 3,
    /** Sub-emitter is triggered manually via code */
    Manual = 4
}
/** @internal */
export declare class ParticleSystemRenderer extends Behaviour {
    renderMode?: ParticleSystemRenderMode;
    particleMaterial?: SpriteMaterial | MeshBasicMaterial;
    trailMaterial?: SpriteMaterial | MeshBasicMaterial;
    particleMesh?: Mesh | string;
    maxParticleSize: number;
    minParticleSize: number;
    velocityScale?: number;
    cameraVelocityScale?: number;
    lengthScale?: number;
    start(): void;
    get transparent(): boolean;
    getMaterial(trailEnabled?: boolean): MeshBasicMaterial | SpriteMaterial | undefined;
    getMesh(_renderMode?: ParticleSystemRenderMode): Mesh<BufferGeometry<import("three").NormalBufferAttributes>, MeshBasicMaterial | SpriteMaterial, import("three").Object3DEventMap>;
}
/**
 * Base class for custom particle behaviors. Extend this to create custom particle logic.
 *
 * Override `initialize()` to set up per-particle state when particles spawn.
 * Override `update()` to modify particles each frame (position, velocity, color, size, etc.).
 * Override `frameUpdate()` for logic that runs once per frame (not per particle).
 *
 * @example Custom wind effect
 * ```ts
 * class WindBehaviour extends ParticleSystemBaseBehaviour {
 *   windStrength = 2;
 *   windDirection = new Vector3(1, 0, 0);
 *
 *   update(particle: Particle, delta: number) {
 *     particle.velocity.addScaledVector(this.windDirection, this.windStrength * delta);
 *   }
 * }
 * ```
 *
 * @see {@link ParticleSystem.addBehaviour} to register your custom behavior
 * @link https://github.com/Alchemist0823/three.quarks
 */
export declare abstract class ParticleSystemBaseBehaviour implements Behavior {
    /** Reference to the particle system this behavior belongs to */
    system: ParticleSystem;
    /** Access to the engine context for timing, input, etc. */
    get context(): Context;
    constructor(ps?: ParticleSystem);
    /** Behavior type identifier used by three.quarks */
    type: string;
    /** Called once when a particle is spawned. Use to initialize per-particle state. */
    initialize(_particle: Particle): void;
    /** Called every frame for each active particle. Use to update particle properties. */
    update(_particle: Particle, _delta: number): void;
    /** Called once per frame before particle updates. Use for shared calculations. */
    frameUpdate(_delta: number): void;
    toJSON(): void;
    clone(): Behavior;
    /** Called when the particle system is reset. */
    reset(): void;
}
export declare const $particleLife: unique symbol;
/**
 * ParticleSystem efficiently handles the motion and rendering of many individual particles.
 * Use it for visual effects like fire, smoke, sparks, rain, magic spells, and more.
 *
 * ![](https://cloud.needle.tools/-/media/qz5nO-raa7dNb_XCBNxHmA.gif)
 * ![](https://cloud.needle.tools/-/media/IKOrLhesy1dKTfQQxx_pLA.gif)
 *
 * **Modules:**
 * Configure particle behavior through modules like {@link EmissionModule}, {@link ShapeModule},
 * {@link ColorOverLifetimeModule}, {@link SizeOverLifetimeModule}, {@link VelocityOverLifetimeModule},
 * {@link NoiseModule}, and {@link TrailModule}.
 *
 * **Custom behaviors:**
 * Add custom particle behaviors by extending {@link ParticleSystemBaseBehaviour} and
 * calling `addBehaviour()`. This gives you full control over particle initialization and updates.
 *
 * **Performance:**
 * Particles are batched together for fast, performant rendering even on low-end devices.
 * Needle Engine uses [three.quarks](https://github.com/Alchemist0823/three.quarks) internally.
 *
 * @example Basic playback control
 * ```ts
 * const ps = myObject.getComponent(ParticleSystem);
 * ps.play();
 * ps.emit(10); // Emit 10 particles immediately
 * ps.pause();
 * ps.stop(true, true); // Stop and clear all particles
 * ```
 *
 * @example Custom particle behavior
 * ```ts
 * class GravityBehaviour extends ParticleSystemBaseBehaviour {
 *   update(particle: Particle, delta: number) {
 *     particle.velocity.y -= 9.8 * delta;
 *   }
 * }
 * particleSystem.addBehaviour(new GravityBehaviour());
 * ```
 *
 * - Example: https://engine.needle.tools/samples/particles
 * - Example: https://engine.needle.tools/samples/particle-bursts
 * - Example: https://engine.needle.tools/samples/particles-on-collision
 *
 * @summary Handles the motion and rendering of many individual particles
 * @category Rendering
 * @group Components
 * @see {@link ParticleSystemBaseBehaviour} for custom particle behaviors
 * @see {@link EmissionModule} for emission configuration
 * @see {@link ShapeModule} for emission shape control
 * @see {@link TrailModule} for particle trails
 * @link https://engine.needle.tools/docs/features/particles.html
 */
export declare class ParticleSystem extends Behaviour implements IParticleSystem {
    play(includeChildren?: boolean): void;
    pause(includeChildren?: boolean): void;
    /** clear=true removes all emitted particles */
    stop(includeChildren?: boolean, clear?: boolean): void;
    /** remove emitted particles and reset time */
    reset(): void;
    private _state?;
    emit(count: number): void;
    get playOnAwake(): boolean;
    set playOnAwake(val: boolean);
    readonly colorOverLifetime: ColorOverLifetimeModule;
    readonly main: MainModule;
    readonly emission: EmissionModule;
    readonly sizeOverLifetime: SizeOverLifetimeModule;
    readonly shape: ShapeModule;
    readonly noise: NoiseModule;
    readonly trails: TrailModule;
    readonly velocityOverLifetime: VelocityOverLifetimeModule;
    readonly limitVelocityOverLifetime: LimitVelocityOverLifetimeModule;
    inheritVelocity: InheritVelocityModule;
    readonly colorBySpeed: ColorBySpeedModule;
    readonly textureSheetAnimation: TextureSheetAnimationModule;
    readonly rotationOverLifetime: RotationOverLifetimeModule;
    readonly rotationBySpeed: RotationBySpeedModule;
    readonly sizeBySpeed: SizeBySpeedModule;
    get renderer(): ParticleSystemRenderer;
    get isPlaying(): boolean;
    get currentParticles(): number;
    get maxParticles(): number;
    get time(): number;
    get duration(): number;
    get deltaTime(): number;
    get scale(): number;
    get cameraScale(): number;
    private _cameraScale;
    get container(): Object3D;
    get worldspace(): boolean;
    get localspace(): boolean;
    private __worldQuaternion;
    get worldQuaternion(): Quaternion;
    private _worldQuaternionInverted;
    get worldQuaternionInverted(): Quaternion;
    private _worldScale;
    get worldScale(): Vector3;
    private _worldPositionFrame;
    private _worldPos;
    get worldPos(): Vector3;
    get matrixWorld(): Matrix4;
    get isSubsystem(): boolean;
    /** Add a custom quarks behaviour to the particle system.
     * You can add a quarks.Behaviour type or derive from {@link ParticleSystemBaseBehaviour}
     * @link https://github.com/Alchemist0823/three.quarks
     * @example
     * ```typescript
     * class MyBehaviour extends ParticleSystemBaseBehaviour {
     *    initialize(particle: Particle) {
     *       // initialize the particle
     *   }
     *    update(particle: Particle, delta: number) {
     *        // do something with the particle
     *   }
     * }
     *
     * const system = gameObject.getComponent(ParticleSystem);
     * system.addBehaviour(new MyBehaviour());
     * ```
    */
    addBehaviour(particleSystemBehaviour: Behavior | ParticleSystemBaseBehaviour): boolean;
    /** Remove a custom quarks behaviour from the particle system. **/
    removeBehaviour(particleSystemBehaviour: Behavior | ParticleSystemBaseBehaviour): boolean;
    /** Removes all behaviours from the particle system
     * **Note:** this will also remove the default behaviours like SizeBehaviour, ColorBehaviour etc.
     */
    removeAllBehaviours(): boolean;
    /** Get the underlying three.quarks particle system behaviours. This can be used to fully customize the behaviour of the particles. */
    get behaviours(): Behavior[] | null;
    /** Get access to the underlying quarks particle system if you need more control
     * @link https://github.com/Alchemist0823/three.quarks
     */
    get particleSystem(): _ParticleSystem | null;
    private _renderer;
    private _batchSystem?;
    private _particleSystem?;
    private _interface;
    private _container;
    private _time;
    private _isPlaying;
    private _isUsedAsSubsystem;
    private _didPreWarm;
    /** called from deserialization */
    private set bursts(value);
    private _bursts?;
    /** called from deserialization */
    private set subEmitterSystems(value);
    private _subEmitterSystems?;
    /** @internal */
    onAfterDeserialize(_: any): void;
    /** @internal */
    awake(): void;
    /** @internal */
    start(): void;
    /** @internal */
    onDestroy(): void;
    /** @internal */
    onEnable(): void;
    onDisable(): void;
    /** @internal */
    onBeforeRender(): void;
    private preWarm;
    private _lastBatchesCount;
    private onSimulate;
    private updateLayers;
    private onUpdate;
    private addSubParticleSystems;
}
/** @internal */
export declare class SubEmitterSystem {
    particleSystem?: ParticleSystem;
    emitProbability: number;
    properties?: number;
    type?: SubEmitterType;
    _deserialize(_context: Context, gameObject: GameObject): void;
}
