import '../../../assert/js/assert.js';
import '../../../globals.js';
/**
 * SphereBucket is a model of a bucket that can be used to store spherical objects.  It manages the addition and removal
 * of the spheres, stacks them as they are added, and manages the stack as spheres are removed.
 *
 * This expects the spheres to have certain properties, please inspect the code to understand the 'contract' between the
 * bucket and the spheres.
 *
 * @author John Blanco
 */
import TProperty from '../../../axon/js/TProperty.js';
import Vector2 from '../../../dot/js/Vector2.js';
import Tandem from '../../../tandem/js/Tandem.js';
import IOType from '../../../tandem/js/types/IOType.js';
import Bucket, { BucketOptions } from './Bucket.js';
type Spherical = {
    userControlledProperty: TProperty<boolean>;
    positionProperty: TProperty<Vector2>;
    destinationProperty: TProperty<Vector2>;
};
type ParticleWithBucketRemovalListener<Particle extends Spherical> = Particle & {
    bucketRemovalListener?: (userControlled: boolean) => void;
};
type SelfOptions = {
    sphereRadius?: number;
    usableWidthProportion?: number;
    verticalParticleOffset?: number | null;
};
type SphereBucketOptions = SelfOptions & BucketOptions;
declare class SphereBucket<Particle extends Spherical> extends Bucket {
    readonly sphereBucketTandem: Tandem;
    private readonly _sphereRadius;
    private readonly _usableWidthProportion;
    private readonly _verticalParticleOffset;
    private _particles;
    constructor(providedOptions?: SphereBucketOptions);
    /**
     * add a particle to the first open position in the stacking order
     */
    addParticleFirstOpen(particle: Particle, animate: boolean): void;
    /**
     * add a particle to the nearest open position in the particle stack
     */
    addParticleNearestOpen(particle: Particle, animate: boolean): void;
    /**
     * Add a particle to the bucket and set up listeners for when the particle is removed.
     */
    private addParticle;
    /**
     * remove a particle from the bucket, updating listeners as necessary
     */
    removeParticle(particle: ParticleWithBucketRemovalListener<Particle>, skipLayout?: boolean): void;
    containsParticle(particle: Particle): boolean;
    /**
     * extract the particle that is closest to the provided position from the bucket
     */
    extractClosestParticle(position: Vector2): Particle | null;
    /**
     * get the list of particles currently contained within this bucket
     */
    getParticleList(): Particle[];
    reset(): void;
    /**
     * check if the provided position is open, i.e. unoccupied by a particle
     */
    private isPositionOpen;
    /**
     * Find the first open position in the stacking order, which is a triangular stack starting from the lower left.
     */
    private getFirstOpenPosition;
    /**
     * get the layer in the stacking order for the provided y (vertical) position
     */
    private getLayerForYPosition;
    /**
     * Get the nearest open position in the stacking order that would be supported if the particle were to be placed
     * there.  This is used for particle stacking.
     */
    private getNearestOpenPosition;
    /**
     * given a layer in the stack, calculate the corresponding Y position for a particle in that layer
     */
    private getYPositionForLayer;
    /**
     * Determine whether a particle is 'dangling', i.e. hanging above an open space in the stack of particles.  Dangling
     * particles should be made to fall to a stable position.
     */
    private isDangling;
    /**
     * count the number of particles that are positioned to support a particle in the provided position
     * @returns - a number from 0 to 2, inclusive
     */
    private countSupportingParticles;
    /**
     * Relayout the particles, generally done after a particle is removed and some other need to fall.
     */
    private relayoutBucketParticles;
    static SphereBucketIO: IOType<any, {
        particles: any[];
    }, {
        particles: unknown;
    }>;
}
export default SphereBucket;
//# sourceMappingURL=SphereBucket.d.ts.map