import Signal from "../../core/events/signal/Signal";

interface Type<T> extends Function {
    new(...args: any[]): T;
}

export class EntityComponentDataset implements Iterable<number> {
    readonly onEntityCreated: Signal<number>
    readonly onEntityRemoved: Signal<number>

    hasComponent<T>(entity: number, component: Type<T>): boolean

    getComponent<T>(entity: number, component: Type<T>): T | undefined

    getComponentSafe<T>(entity: number, component: Type<T>): T

    getComponentByIndex<T>(entity: number, componentIndex: number): T | undefined

    addComponentToEntity<T>(entityIndex: number, componentInstance: T): void

    removeComponentFromEntity<T>(entityIndex: number, klass: Type<T>): void

    setComponentTypeMap(types: any[]): void

    getComponentTypeMap(): (Type<any> & { typeName?: string })[]

    getComponentClassByName<T>(name: string): Type<T> | null

    getAnyComponent<T>(type: Type<T>): { entity: number, component: T | null }

    computeComponentTypeIndex<T>(type: Type<T>): number

    registerComponentType<T>(componentType: Type<T>): boolean

    registerManyComponentTypes(componentTypes: Type<any>[]): boolean

    createEntity(): number

    createEntitySpecific(entityId: number): void

    removeEntity(entityIndex: number): boolean

    removeEntities(entityIndices: number[]): void

    entityExists(entityIndex: number): boolean

    traverseEntities(classes: any[], visitor: (...params: any) => boolean, thisArg?: any): void

    traverseComponents<T>(klass: Type<T>, visitor: (component: T, entity: number) => boolean, thisArg?: any): void

    addEntityEventListener<T>(entity: number, eventName: string, listener: (event: T, entity: number) => any, thisArg?: any): void

    removeEntityEventListener<T>(entity: number, eventName: string, listener: (event: T, entity: number) => any, thisArg?: any): boolean

    sendEvent<T>(entity: number, name: string, event?: T): void

    isEmpty(): boolean

    getEntityGeneration(entity: number): number
}
