import * as i0 from '@angular/core';
import { InjectionToken, NgZone, Injector } from '@angular/core';
import { ɵAngularFireSchedulers as _AngularFireSchedulers } from '@angular/fire';
import { AppCheckInstances } from '@angular/fire/app-check';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { FirebaseOptions } from 'firebase/app';
import firebase from 'firebase/compat/app';
import * as rxjs from 'rxjs';
import { Observable, SchedulerLike } from 'rxjs';

type FirebaseOperation = string | firebase.database.Reference | firebase.database.DataSnapshot;
interface AngularFireList<T> {
    query: DatabaseQuery;
    valueChanges(events?: ChildEvent[], options?: unknown): Observable<T[]>;
    valueChanges<K extends string>(events?: ChildEvent[], options?: {
        idField: K;
    }): Observable<(T & {
        [T in K]?: string;
    })[]>;
    snapshotChanges(events?: ChildEvent[]): Observable<SnapshotAction<T>[]>;
    stateChanges(events?: ChildEvent[]): Observable<SnapshotAction<T>>;
    auditTrail(events?: ChildEvent[]): Observable<SnapshotAction<T>[]>;
    update(item: FirebaseOperation, data: Partial<T>): Promise<void>;
    set(item: FirebaseOperation, data: T): Promise<void>;
    push(data: T): firebase.database.ThenableReference;
    remove(item?: FirebaseOperation): Promise<void>;
}
interface AngularFireObject<T> {
    query: DatabaseQuery;
    valueChanges(): Observable<T | null>;
    snapshotChanges(): Observable<SnapshotAction<T>>;
    update(data: Partial<T>): Promise<void>;
    set(data: T): Promise<void>;
    remove(): Promise<void>;
}
type QueryFn = (ref: DatabaseReference) => DatabaseQuery;
type ChildEvent = 'child_added' | 'child_removed' | 'child_changed' | 'child_moved';
type ListenEvent = 'value' | ChildEvent;
interface Action<T> {
    type: ListenEvent;
    payload: T;
}
interface AngularFireAction<T> extends Action<T> {
    prevKey: string | null | undefined;
    key: string | null;
}
type SnapshotAction<T> = AngularFireAction<DatabaseSnapshot<T>>;
interface DatabaseSnapshotExists<T> extends firebase.database.DataSnapshot {
    exists(): true;
    val(): T;
    forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
}
interface DatabaseSnapshotDoesNotExist<T> extends firebase.database.DataSnapshot {
    exists(): false;
    val(): null;
    forEach(action: (a: DatabaseSnapshot<T>) => boolean): boolean;
}
type DatabaseSnapshot<T> = DatabaseSnapshotExists<T> | DatabaseSnapshotDoesNotExist<T>;
type DatabaseReference = firebase.database.Reference;
type DatabaseQuery = firebase.database.Query;
type QueryReference = DatabaseReference | DatabaseQuery;
type PathReference = QueryReference | string;

declare const URL: InjectionToken<string>;
declare const USE_EMULATOR: InjectionToken<[host: string, port: number, options?: {
    mockUserToken?: firebase.database.EmulatorMockTokenOptions | string;
}]>;
declare class AngularFireDatabase {
    schedulers: _AngularFireSchedulers;
    readonly database: firebase.database.Database;
    private readonly injector;
    constructor(options: FirebaseOptions, name: string | null | undefined, databaseURL: string | null, platformId: Object, zone: NgZone, schedulers: _AngularFireSchedulers, _useEmulator: any, // tuple isn't working here
    auth: AngularFireAuth, useAuthEmulator: any, authSettings: any, // can't use firebase.auth.AuthSettings here
    tenantId: string | null, languageCode: string | null, useDeviceLanguage: boolean | null, persistence: string | null, _appCheckInstances: AppCheckInstances);
    list<T>(pathOrRef: PathReference, queryFn?: QueryFn): AngularFireList<T>;
    object<T>(pathOrRef: PathReference): AngularFireObject<T>;
    createPushId(): string;
    static ɵfac: i0.ɵɵFactoryDeclaration<AngularFireDatabase, [null, { optional: true; }, { optional: true; }, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
    static ɵprov: i0.ɵɵInjectableDeclaration<AngularFireDatabase>;
}

declare function listChanges<T = any>(ref: DatabaseQuery, events: ChildEvent[], scheduler?: SchedulerLike): Observable<SnapshotAction<T>[]>;

declare function createListReference<T = any>(query: DatabaseQuery, afDatabase: AngularFireDatabase, injector?: Injector): AngularFireList<T>;

declare function snapshotChanges<T>(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike): Observable<SnapshotAction<T>[]>;

declare function stateChanges<T>(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike): rxjs.Observable<AngularFireAction<DatabaseSnapshot<T>>>;

declare function auditTrail<T>(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike): Observable<SnapshotAction<T>[]>;

/**
 * Create an observable from a Database Reference or Database Query.
 * @param ref Database Reference
 * @param event Listen event type ('value', 'added', 'changed', 'removed', 'moved')
 * @param listenType 'on' or 'once'
 * @param scheduler - Rxjs scheduler
 */
declare function fromRef<T>(ref: DatabaseQuery, event: ListenEvent, listenType?: string, scheduler?: SchedulerLike): Observable<AngularFireAction<DatabaseSnapshot<T>>>;

declare class AngularFireDatabaseModule {
    constructor();
    static ɵfac: i0.ɵɵFactoryDeclaration<AngularFireDatabaseModule, never>;
    static ɵmod: i0.ɵɵNgModuleDeclaration<AngularFireDatabaseModule, never, never, never>;
    static ɵinj: i0.ɵɵInjectorDeclaration<AngularFireDatabaseModule>;
}

export { AngularFireDatabase, AngularFireDatabaseModule, URL, USE_EMULATOR, auditTrail, createListReference, fromRef, listChanges, snapshotChanges, stateChanges };
export type { Action, AngularFireAction, AngularFireList, AngularFireObject, ChildEvent, DatabaseSnapshot, ListenEvent, PathReference, QueryFn, SnapshotAction };
