import { BoundingBox } from '../Collision/BoundingBox';
import { Engine } from '../Engine';
import { Vector } from '../Math/vector';
import { Logger } from '../Util/Log';
import { Entity, EntityEvents } from '../EntityComponentSystem/Entity';
import { TransformComponent } from '../EntityComponentSystem/Components/TransformComponent';
import { ExcaliburGraphicsContext, Graphic } from '../Graphics';
import { ColliderComponent } from '../Collision/ColliderComponent';
import { Collider } from '../Collision/Colliders/Collider';
import { PostDrawEvent, PostUpdateEvent, PreDrawEvent, PreUpdateEvent } from '../Events';
import { EventEmitter, EventKey, Handler, Subscription } from '../EventEmitter';
import { DebugConfig } from '../Debug';
import { PointerComponent } from '../Input/PointerComponent';
import { PointerEvent } from '../Input/PointerEvent';
import { PointerEventReceiver } from '../Input/PointerEventReceiver';
import { HasNestedPointerEvents } from '../Input/PointerEventsToObjectDispatcher';
export interface TileMapOptions {
    /**
     * Optionally name the tile map
     */
    name?: string;
    /**
     * Optionally specify the position of the tile map
     */
    pos?: Vector;
    /**
     * Width of an individual tile in pixels
     */
    tileWidth: number;
    /**
     * Height of an individual tile in pixels
     */
    tileHeight: number;
    /**
     * The number of tile columns, or the number of tiles wide
     */
    columns: number;
    /**
     * The number of tile  rows, or the number of tiles high
     */
    rows: number;
    /**
     * Optionally render from the top of the graphic, by default tiles are rendered from the bottom
     */
    renderFromTopOfGraphic?: boolean;
    /**
     * Optionally configure the meshing lookbehind for Tilemap, Tilemaps combine solid tiles into optimal
     * geometry and the lookbehind configures how far back the Tilemap to look for geometry when combining. Meshing
     * is an expensive operation, so when the Tilemap geometry is invalidated it must be recalculated.
     *
     * Default is 10 slots, but if your Tilemap does not change positions or solid tiles often you can increase this to
     * Infinity.
     */
    meshingLookBehind?: number;
}
export type TilePointerEvents = {
    pointerup: PointerEvent;
    pointerdown: PointerEvent;
    pointermove: PointerEvent;
    pointercancel: PointerEvent;
    pointerenter: PointerEvent;
    pointerleave: PointerEvent;
};
export type TileMapEvents = EntityEvents & TilePointerEvents & {
    preupdate: PreUpdateEvent<TileMap>;
    postupdate: PostUpdateEvent<TileMap>;
    predraw: PreDrawEvent;
    postdraw: PostDrawEvent;
};
export declare const TileMapEvents: {
    PreUpdate: string;
    PostUpdate: string;
    PreDraw: string;
    PostDraw: string;
    PointerUp: string;
    PointerDown: string;
    PointerMove: string;
    PointerCancel: string;
};
/**
 * The TileMap provides a mechanism for doing flat 2D tiles rendered in a grid.
 *
 * TileMaps are useful for top down or side scrolling grid oriented games.
 */
export declare class TileMap extends Entity implements HasNestedPointerEvents {
    events: EventEmitter<TileMapEvents>;
    private _token;
    private _engine;
    logger: Logger;
    readonly tiles: Tile[];
    private _rows;
    private _cols;
    readonly tileWidth: number;
    readonly tileHeight: number;
    readonly rows: number;
    readonly columns: number;
    renderFromTopOfGraphic: boolean;
    meshingLookBehind: number;
    private _collidersDirty;
    private _pointerEventDispatcher;
    flagCollidersDirty(): void;
    flagTilesDirty(): void;
    pointer: PointerComponent;
    transform: TransformComponent;
    private _motion;
    private _graphics;
    collider: ColliderComponent;
    private _composite;
    get x(): number;
    set x(val: number);
    get y(): number;
    set y(val: number);
    get z(): number;
    set z(val: number);
    private _oldRotation;
    get rotation(): number;
    set rotation(val: number);
    private _oldScale;
    get scale(): Vector;
    set scale(val: Vector);
    private _oldPos;
    get pos(): Vector;
    set pos(val: Vector);
    get vel(): Vector;
    set vel(val: Vector);
    /**
     * Width of the whole tile map in pixels
     */
    get width(): number;
    /**
     * Height of the whole tilemap in pixels
     */
    get height(): number;
    emit<TEventName extends EventKey<TileMapEvents>>(eventName: TEventName, event: TileMapEvents[TEventName]): void;
    emit(eventName: string, event?: any): void;
    on<TEventName extends EventKey<TileMapEvents>>(eventName: TEventName, handler: Handler<TileMapEvents[TEventName]>): Subscription;
    on(eventName: string, handler: Handler<unknown>): Subscription;
    once<TEventName extends EventKey<TileMapEvents>>(eventName: TEventName, handler: Handler<TileMapEvents[TEventName]>): Subscription;
    once(eventName: string, handler: Handler<unknown>): Subscription;
    off<TEventName extends EventKey<TileMapEvents>>(eventName: TEventName, handler: Handler<TileMapEvents[TEventName]>): void;
    off(eventName: string, handler: Handler<unknown>): void;
    off(eventName: string): void;
    /**
     * @param options
     */
    constructor(options: TileMapOptions);
    _initialize(engine: Engine): void;
    private _originalOffsets;
    private _getOrSetColliderOriginalOffset;
    /**
     * Tiles colliders based on the solid tiles in the tilemap.
     */
    private _updateColliders;
    /**
     * Returns the {@apilink Tile} by index (row major order)
     *
     * Returns null if out of bounds
     */
    getTileByIndex(index: number): Tile | null;
    /**
     * Returns the {@apilink Tile} by its x and y integer coordinates
     *
     * Returns null if out of bounds
     *
     * For example, if I want the tile in fifth column (x), and second row (y):
     * `getTile(4, 1)` 0 based, so 0 is the first in row/column
     */
    getTile(x: number, y: number): Tile | null;
    /**
     * Returns the {@apilink Tile} by testing a point in world coordinates,
     * returns `null` if no Tile was found.
     */
    getTileByPoint(point: Vector): Tile | null;
    private _getTileCoordinates;
    getRows(): readonly Tile[][];
    getColumns(): readonly Tile[][];
    /**
     * Returns the on screen tiles for a tilemap, this will overshoot by a small amount because of the internal quad tree data structure.
     *
     * Useful if you need to perform specific logic on onscreen tiles
     */
    getOnScreenTiles(): readonly Tile[];
    /**
     * @internal
     */
    _processPointerToObject(receiver: PointerEventReceiver): void;
    /**
     * @internal
     */
    _dispatchPointerEvents(receiver: PointerEventReceiver): void;
    update(engine: Engine, elapsed: number): void;
    /**
     * Draws the tile map to the screen. Called by the {@apilink Scene}.
     * @param ctx ExcaliburGraphicsContext
     * @param elapsed  The number of milliseconds since the last draw
     */
    draw(ctx: ExcaliburGraphicsContext, elapsed: number): void;
    debug(gfx: ExcaliburGraphicsContext, debugFlags: DebugConfig): void;
}
export interface TileOptions {
    /**
     * Integer tile x coordinate
     */
    x: number;
    /**
     * Integer tile y coordinate
     */
    y: number;
    map: TileMap;
    solid?: boolean;
    graphics?: Graphic[];
}
/**
 * TileMap Tile
 *
 * A light-weight object that occupies a space in a collision map. Generally
 * created by a {@apilink TileMap}.
 *
 * Tiles can draw multiple sprites. Note that the order of drawing is the order
 * of the sprites in the array so the last one will be drawn on top. You can
 * use transparency to create layers this way.
 */
export declare class Tile {
    private _bounds;
    private _geometry;
    private _pos;
    private _posDirty;
    events: EventEmitter<TilePointerEvents>;
    /**
     * Return the world position of the top left corner of the tile
     */
    get pos(): Vector;
    /**
     * Integer x coordinate of the tile
     */
    readonly x: number;
    /**
     * Integer y coordinate of the tile
     */
    readonly y: number;
    private _width;
    /**
     * Width of the tile in pixels
     */
    get width(): number;
    private _height;
    /**
     * Height of the tile in pixels
     */
    get height(): number;
    /**
     * Reference to the TileMap this tile is associated with
     */
    map: TileMap;
    private _solid;
    /**
     * Wether this tile should be treated as solid by the tilemap
     */
    get solid(): boolean;
    /**
     * Wether this tile should be treated as solid by the tilemap
     */
    set solid(val: boolean);
    private _graphics;
    private _offsets;
    /**
     * Current list of graphics for this tile
     */
    getGraphics(): readonly Graphic[];
    /**
     * Current list of offsets for this tile's graphics
     */
    getGraphicsOffsets(): readonly Vector[];
    /**
     * Add another {@apilink Graphic} to this TileMap tile
     * @param graphic
     */
    addGraphic(graphic: Graphic, options?: {
        offset?: Vector;
    }): void;
    /**
     * Remove an instance of a {@apilink Graphic} from this tile
     */
    removeGraphic(graphic: Graphic): void;
    /**
     * Clear all graphics from this tile
     */
    clearGraphics(): void;
    /**
     * Current list of colliders for this tile
     */
    private _colliders;
    /**
     * Returns the list of colliders
     */
    getColliders(): readonly Collider[];
    /**
     * Adds a custom collider to the {@apilink Tile} to use instead of it's bounds
     *
     * If no collider is set but {@apilink Tile.solid} is set, the tile bounds are used as a collider.
     *
     * **Note!** the {@apilink Tile.solid} must be set to true for it to act as a "fixed" collider
     * @param collider
     */
    addCollider(collider: Collider): void;
    /**
     * Removes a collider from the {@apilink Tile}
     * @param collider
     */
    removeCollider(collider: Collider): void;
    /**
     * Clears all colliders from the {@apilink Tile}
     */
    clearColliders(): void;
    /**
     * Arbitrary data storage per tile, useful for any game specific data
     */
    data: Map<string, any>;
    constructor(options: TileOptions);
    flagDirty(): boolean;
    private _recalculate;
    /**
     * Tile bounds in world space
     */
    get bounds(): BoundingBox;
    get defaultGeometry(): BoundingBox;
    /**
     * Tile position in world space
     */
    get center(): Vector;
    emit<TEventName extends EventKey<TilePointerEvents>>(eventName: TEventName, event: TilePointerEvents[TEventName]): void;
    emit(eventName: string, event?: any): void;
    on<TEventName extends EventKey<TilePointerEvents>>(eventName: TEventName, handler: Handler<TilePointerEvents[TEventName]>): Subscription;
    on(eventName: string, handler: Handler<unknown>): Subscription;
    once<TEventName extends EventKey<TilePointerEvents>>(eventName: TEventName, handler: Handler<TilePointerEvents[TEventName]>): Subscription;
    once(eventName: string, handler: Handler<unknown>): Subscription;
    off<TEventName extends EventKey<TilePointerEvents>>(eventName: TEventName, handler: Handler<TilePointerEvents[TEventName]>): void;
    off(eventName: string, handler: Handler<unknown>): void;
    off(eventName: string): void;
}
