import { IDictionary } from "common-types";
import { SerializedQuery } from "serialized-query";
import { FirebaseDatabase, DataSnapshot, EventType, Reference } from "@firebase/database-types";
export declare type FirebaseNamespace = import("@firebase/app-types").FirebaseNamespace;
import { IFirebaseConfig, IMockLoadingState, IFirebaseWatchHandler, IClientEmitter, IAdminEmitter } from "./types";
import { IFirebaseListener, IFirebaseConnectionCallback } from ".";
declare type Mock = import("firemock").Mock;
declare type IMockConfigOptions = import("firemock").IMockConfigOptions;
/** time by which the dynamically loaded mock library should be loaded */
export declare const MOCK_LOADING_TIMEOUT = 2000;
export declare abstract class RealTimeDB<A = any> {
    protected _isAdminApi: boolean;
    get isMockDb(): boolean;
    get isAdminApi(): boolean;
    /**
     * **getPushKey**
     *
     * Get's a push-key from the server at a given path. This ensures that multiple
     * client's who are writing to the database will use the server's time rather than
     * their own local time.
     *
     * @param path the path in the database where the push-key will be pushed to
     */
    getPushKey(path: string): Promise<string>;
    get mock(): Mock;
    get isConnected(): boolean;
    get config(): IFirebaseConfig;
    static connect: (config: any) => Promise<any>;
    /** how many miliseconds before the attempt to connect to DB is timed out */
    CONNECTION_TIMEOUT: number;
    /** Logs debugging information to the console */
    enableDatabaseLogging: (logger?: boolean | ((a: string) => any), persistent?: boolean) => any;
    protected abstract _eventManager: IClientEmitter | IAdminEmitter;
    protected abstract _clientType: "client" | "admin";
    protected _isConnected: boolean;
    protected _mockLoadingState: IMockLoadingState;
    protected _mock: Mock;
    protected _resetMockDb: () => void;
    protected _waitingForConnection: Array<() => void>;
    protected _debugging: boolean;
    protected _mocking: boolean;
    protected _allowMocking: boolean;
    protected _onConnected: IFirebaseListener[];
    protected _onDisconnected: IFirebaseListener[];
    protected app: any;
    protected _database: FirebaseDatabase;
    /** the config the db was started with */
    protected _config: IFirebaseConfig;
    protected abstract _auth: any;
    constructor(config?: IFirebaseConfig);
    /**
     * called by `client` and `admin` at end of constructor
     */
    initialize(config?: IFirebaseConfig): void;
    abstract auth(): Promise<A>;
    /**
     * watch
     *
     * Watch for firebase events based on a DB path or `SerializedQuery` (path plus query elements)
     *
     * @param target a database path or a SerializedQuery
     * @param events an event type or an array of event types (e.g., "value", "child_added")
     * @param cb the callback function to call when event triggered
     */
    watch(target: string | SerializedQuery<any>, events: EventType | EventType[], cb: IFirebaseWatchHandler): void;
    unWatch(events?: EventType | EventType[], cb?: any): void;
    /**
     * Get a Firebase SerializedQuery reference
     *
     * @param path path for query
     */
    query<T extends object = any>(path: string): SerializedQuery<T>;
    /** Get a DB reference for a given path in Firebase */
    ref(path?: string): Reference;
    /**
     * Provides a promise-based way of waiting for the connection to be
     * established before resolving
     */
    waitForConnection(): Promise<this>;
    /**
     * get a notification when DB is connected; returns a unique id
     * which can be used to remove the callback. You may, optionally,
     * state a unique id of your own.
     *
     * By default the callback will receive the database connection as it's
     * `this`/context. This means that any locally defined variables will be
     * dereferenced an unavailable. If you want to retain a connection to this
     * state you should include the optional _context_ parameter and your
     * callback will get a parameter passed back with this context available.
     */
    notifyWhenConnected(cb: IFirebaseConnectionCallback, id?: string, 
    /**
     * additional context/pointers for your callback to use when activated
     */
    ctx?: IDictionary): string;
    /**
     * removes a callback notification previously registered
     */
    removeNotificationOnConnection(id: string): this;
    /** set a "value" in the database at a given path */
    set<T = any>(path: string, value: T): Promise<void>;
    /**
     * **multiPathSet**
     *
     * Equivalent to Firebase's traditional "multi-path updates" which are
     * in behaviour are really "multi-path SETs". The basic idea is that
     * all the _keys_ are database paths and the _values_ are **destructive** values.
     *
     * An example of
     * what you might might look like:
     *
     * ```json
     * {
     *  "path/to/my/data": "my destructive data",
     *  "another/path/to/write/to": "everyone loves monkeys"
     * }
     * ```
     *
     * When we say "destructive" we mean that whatever value you put at the give path will
     * _overwrite_ the data that was there rather than "update" it. This not hard to
     * understand because we've given this function a name with "SET" in the name but
     * in the real-time database this actual translates into an alternative use of the
     * "update" command which is described here:
     * [Introducing Multi-Location Updates.](https://firebase.googleblog.com/2015/09/introducing-multi-location-updates-and_86.html)
     *
     * This functionality, in the end, is SUPER useful as it provides a means to achieve
     * transactional functionality (aka, either all paths are written to or none are).
     *
     * **Note:** because _dot notation_ for paths is not uncommon you can notate
     * the paths with `.` instead of `/`
     */
    multiPathSet(updates: IDictionary): Promise<void>;
    /**
     * **update**
     *
     * Update the database at a given path. Note that this operation is
     * **non-destructive**, so assuming that the value you are passing in
     * a POJO/object then the properties sent in will be updated but if
     * properties that exist in the DB, but not in the value passed in,
     * then these properties will _not_ be changed.
     *
     * [API Docs](https://firebase.google.com/docs/reference/js/firebase.database.Reference#update)
     */
    update<T = any>(path: string, value: Partial<T>): Promise<void>;
    /**
     * **remove**
     *
     * Removes a path from the database. By default if you attempt to
     * remove a path in the database which _didn't_ exist it will throw
     * a `abstracted-firebase/remove` error. If you'd prefer for this
     * error to be ignored than you can pass in **true** to the `ignoreMissing`
     * parameter.
     *
     * [API  Docs](https://firebase.google.com/docs/reference/js/firebase.database.Reference#remove)
     */
    remove<T = any>(path: string, ignoreMissing?: boolean): Promise<any>;
    /**
     * **getSnapshot**
     *
     * returns the Firebase snapshot at a given path in the database
     */
    getSnapshot<T extends object = any>(path: string | SerializedQuery<T>): Promise<DataSnapshot>;
    /**
     * **getValue**
     *
     * Returns the JS value at a given path in the database. This method is a
     * typescript _generic_ which defaults to `any` but you can set the type to
     * whatever value you expect at that path in the database.
     */
    getValue<T = any>(path: string): Promise<T>;
    /**
     * **getRecord**
     *
     * Gets a snapshot from a given path in the Firebase DB
     * and converts it to a JS object where the snapshot's key
     * is included as part of the record (as `id` by default)
     */
    getRecord<T extends object = any>(path: string | SerializedQuery<T>, idProp?: string): Promise<T>;
    /**
     * **getList**
     *
     * Get a list of a given type (defaults to _any_). Assumes that the
     * "key" for the record is the `id` property but that can be changed
     * with the optional `idProp` parameter.
     *
     * @param path the path in the database to
     * @param idProp
     */
    getList<T extends object = any>(path: string | SerializedQuery<T>, idProp?: string): Promise<T[]>;
    /**
     * **getSortedList**
     *
     * getSortedList() will return the sorting order that was defined in the Firebase
     * Query. This _can_ be useful but often the sort orders
     * really intended for the server only (so that filteration
     * is done on the right set of data before sending to client).
     *
     * @param query Firebase "query ref"
     * @param idProp what property name should the Firebase key be converted to (default is "id")
     */
    getSortedList<T = any>(query: any, idProp?: string): Promise<T[]>;
    /**
     * **push**
     *
     * Pushes a value (typically a hash) under a given path in the
     * database but allowing Firebase to insert a unique "push key"
     * to ensure the value is placed into a Dictionary/Hash structure
     * of the form of `/{path}/{pushkey}/{value}`
     *
     * Note, the pushkey will be generated on the Firebase side and
     * Firebase keys are guarenteed to be unique and embedded into the
     * UUID is precise time-based information so you _can_ count on
     * the keys to have a natural time based sort order.
     */
    push<T = any>(path: string, value: T): Promise<void>;
    /**
     * **exists**
     *
     * Validates the existance of a path in the database
     */
    exists(path: string): Promise<boolean>;
    /**
     * monitorConnection
     *
     * allows interested parties to hook into event messages when the
     * DB connection either connects or disconnects
     */
    protected _monitorConnection(snap: DataSnapshot): void;
    protected abstract connectToFirebase(config: any): Promise<void>;
    protected abstract listenForConnectionStatus(): void;
    /**
     * When using the **Firebase** Authentication solution, the primary API
     * resides off the `db.auth()` call but each _provider_ also has an API
     * that can be useful and this has links to various providers.
     */
    get authProviders(): any;
    /**
     * **getFireMock**
     *
     * Asynchronously imports both `FireMock` and the `Faker` libraries
     * then sets `isConnected` to **true**
     */
    protected getFireMock(config?: IMockConfigOptions): Promise<void>;
}
export {};
