import { HGrid, HDict, HRef } from 'haystack-core';
import { Ids } from '../../util/hval';
import { Subject } from './Subject';
import { WatchEvent, WatchEventType, WatchChanged } from './WatchEvent';
/**
 * The default poll rate in seconds.
 */
export declare const DEFAULT_POLL_RATE_SECS = 5;
/**
 * A watch event callback.
 */
export interface WatchEventCallback {
    (event: WatchEvent, watch: Watch): void;
}
/**
 * A haystack Watch.
 */
export declare class Watch {
    #private;
    /**
     * The grid for the watch.
     */
    readonly grid: HGrid;
    /**
     * Constructs a new watch.
     *
     * Please note, all watches must be closed when no longer used.
     *
     * @param watchDisplay A client side display name for the watch.
     * @param subject The watch will observe this subject.
     * @param grid An empty grid to use for the watch.
     */
    constructor(watchDisplay: string, subject: Subject, grid?: HGrid);
    /**
     * Returns a list of watches.
     *
     * ```typescript
     * hs.Watch.watches.forEach((watch: Watch): void => {
     *   console.log(`We have watch: ${watch.display}`)
     * })
     * ```
     *
     * @returns A list of all open watches.
     */
    static get watches(): Watch[];
    /**
     * Inspect all the watches available.
     *
     * ```typescript
     * hs.Watch.inspectAll()
     * ```
     */
    static inspectAll(): void;
    /**
     * Dump the watch to the local console output.
     *
     * ```typescript
     * watch.inspect()
     * ```
     *
     * @returns The value instance.
     */
    inspect(): this;
    /**
     * Dump the watch's subject to the local console output.
     *
     * ```typescript
     * watch.inspectSubject()
     * ```
     *
     * @returns The value instance.
     */
    inspectSubject(): this;
    /**
     * ```typescript
     * console.log(watch.display)
     * ```
     *
     * @returns The display name of the watch.
     */
    get display(): string;
    /**
     * @returns A string representation of a watch.
     */
    toString(): string;
    /**
     * Returns true if the watch is closed.
     *
     * ```typescript
     * if (watch.isClosed()) {
     *   // Do something
     * }
     * ```
     *
     * @returns True if the watch is closed. A closed watch
     * can no longer be used.
     */
    isClosed(): boolean;
    /**
     * @throws An error if the watch is closed.
     */
    private throwErrorIfClosed;
    /**
     * Return a new opened watch.
     *
     * Please note, all watches must be closed when no longer used.
     *
     * @param options.subject The watch subject.
     * @param options.ids The ids to watch.
     * @param options.display Display name for the watch.
     * @param options.grid Optional grid to use for the watch.
     * @returns An opened watch.
     */
    static open({ subject, ids, display, grid, }: {
        subject: Subject;
        ids: Ids;
        display: string;
        grid?: HGrid;
    }): Promise<Watch>;
    /**
     * Close all watches for the given subject.
     *
     * Please note, this method doesn't normally need to be called
     * and is designed to be used internally. If you want
     * to close a watch then please just call `Watch.#close()` instead.
     *
     * @param subject The subject to close watches for.
     */
    static close(subject: Subject): Promise<void>;
    /**
     * Add records to watch.
     *
     * ```typescript
     * await watch.add('@someid')
     * ```
     *
     * @param ids The ids to add.
     */
    add(ids: Ids): Promise<void>;
    /**
     * Add new dicts to the watch's grid.
     *
     * @param toAdd The ids to add.
     * @returns The ids added and those in error.
     */
    private addDictsToGrid;
    /**
     * Remove records to watch.
     *
     * This is called to stop watching records.
     *
     * ```typescript
     * await watch.remove('@someid')
     * ```
     *
     * @param ids The ids to remove.
     */
    remove(ids: Ids): Promise<void>;
    /**
     * Removes dicts from the watch's grid.
     *
     * @param toRemove The ids to remove.
     * @returns The removed ids.
     */
    private removeDictsFromGrid;
    /**
     * Completely refresh the watch.
     *
     * ```typescript
     * await watch.refresh()
     * ```
     */
    refresh(): Promise<void>;
    /**
     * Rebuild the cache of dicts.
     */
    private rebuildDictCache;
    /**
     * Changed event callback.
     */
    private $onChanged;
    /**
     * Clear all watched items from the watch.
     *
     * Please note, this will not close the watch or remove any
     * associated method handlers.
     *
     * ```typescript
     * await watch.clear()
     * ```
     */
    clear(): Promise<void>;
    /**
     * Close the watch.
     *
     * After this has been called, the underlying watch will be destroyed
     * and will be no longer active. The watch is effectively 'dead' after this
     * has been called.
     *
     * ```typescript
     * // We must always close a watch once we've finished using it.
     * await watch.close()
     * ```
     */
    close(): Promise<void>;
    /**
     * Returns the poll rate in seconds.
     *
     * ```typescript
     * const pollRate = watch.pollRate
     * ```
     *
     * @returns The poll rate for this watch.
     */
    get pollRate(): number;
    /**
     * Attempt to set a new poll rate in seconds for the watch.
     *
     * Please note, this value may be ignored.
     *
     * ```typescript
     * // Set the poll rate to 10 seconds.
     * watch.pollRate = 10
     * ```
     *
     * @param pollRate The poll rate.
     */
    set pollRate(pollRate: number);
    /**
     * Add an event handler for the specified event type.
     *
     * This is used to listen for watch events.
     *
     * ```typescript
     * watch.on(WatchEventType.Changed, (event: WatchEvent, emitter: WatchEventEmitter): void {
     *  // Do something with the event!
     * })
     * ```
     *
     * @param eventType The event type to add the event for.
     * @param callback The callback handler.
     * @return The emitter instance.
     * @throws An error if the watch is already closed.
     */
    on(eventType: WatchEventType, callback: WatchEventCallback): this;
    /**
     * Remove an event handler from a watch.
     *
     * ```typescript
     * watch.off(WatchEventType.Changed, cb)
     * ```
     *
     * @param eventType event type to remove.
     * @param callback callback to remove.
     * @return The emitter instance.
     */
    off(eventType: WatchEventType, callback: WatchEventCallback): this;
    /**
     * Fire an event callback.
     *
     * @param event The event object.
     * @return The emitter instance.
     */
    fire(event: WatchEvent): this;
    /**
     * Return the callbacks for the event type or all callbacks if
     * the event type is not specified.
     *
     * ```typescript
     * const anArrayOfCallbacks = watch.getCallbacks()
     * ```
     *
     * @param eventType Optional event type.
     * @returns The callbacks.
     */
    getCallbacks(eventType?: WatchEventType): WatchEventCallback[];
    /**
     * Return true if there are callback handlers for the specified event type.
     *
     * If there event type is not specified then check to see if there are any callback handlers.
     *
     * ```typescript
     * if (watch.hasCallbacks()) {
     *   // Do something...
     * }
     * ```
     *
     * @returns True if there are callbacks.
     */
    hasCallbacks(eventType?: WatchEventType): boolean;
    /**
     * Clear all callback event handlers on the watch.
     *
     * ```typescript
     * // Clear all callbacks from the watch.
     * watch.clearCallbacks()
     * ```
     *
     * @return The emitter instance.
     */
    clearCallbacks(): this;
    /**
     * Builds a changed callback handler based upon the parameters.
     *
     * Please note, the returned callback should be used to unregister the callback
     * handler from the watch.
     *
     * ```typescript
     * // Add event handlers. We're only interested in 'curVal' changes.
     * watch.changed({
     *   interests: ['curVal'],
     *   callback: (event) => console.log(event)
     * })
     *
     * ...
     *
     * // Add event handlers. We're only interested in changes to curVal when it's above
     * // a certain value.
     * watch.changed({
     * 	interests: ['curVal'],
     * 	condition: 'curVal > 50°F',
     * 	callback: event => console.log(event),
     * })
     * ```
     *
     * @param options.interests Optional interests. This is a list of tags on a record
     * the caller is interested. If specified, an event will only be fired if a record
     * with one of these tags is changed, added or removed.
     * @param options.condition Optional haystack filter condition used to filter a change
     * before any callback is invoked.
     * @param options.callback The callback.
     * @returns The built callback handler.
     * @throws An error if the haystack filter is invalid.
     */
    changed({ interests, condition, callback, }: {
        interests?: string[];
        condition?: string;
        callback: WatchEventCallback;
    }): WatchEventCallback;
    /**
     * Called to remove dicts from the watch's grid.
     *
     * This method can be overridden to track grid mutations.
     *
     * @param filter The filter to remove items by.
     */
    removeFromGrid(filter: string): void;
    /**
     * Add the dicts to the watch's grid.
     *
     * This method can be overridden to track grid mutations.
     *
     * @param dicts The dicts to add to the grid.
     */
    addToGrid(dicts: HDict[]): void;
    /**
     * Empty the grid.
     *
     * This method can be overridden to track grid mutations.
     */
    clearGrid(): void;
    /**
     * Update the grid with the new events information.
     *
     * @param options.dictIndexes An object with ids to indexes.
     * @param options.events The events to update the grid with.
     */
    updateGrid({ idsToGridIndexes, events, }: {
        idsToGridIndexes: {
            [prop: string]: number;
        };
        events: {
            [prop: string]: WatchChanged;
        };
    }): void;
    /**
     * Update the grid with the new events.
     *
     * @param idsToGridIndexes A cache of ids to dict indexes in the grid.
     * @param grid The grid to update.
     * @param events The events to update the grid with.
     */
    static updateGrid(idsToGridIndexes: {
        [prop: string]: number;
    }, grid: HGrid, events: {
        [prop: string]: WatchChanged;
    }): void;
    /**
     * Compute a new poll rate from all the open watches.
     */
    private computeSubjectPollRate;
    /**
     * @returns The ids of the records that are in error
     * and can't be watched on the server.
     */
    get errors(): string[];
    /**
     * @returns the ids as refs of the records that in error
     * and can't be watched on the server.
     */
    get errorRefs(): HRef[];
    /**
     * @returns True if the watch has errors.
     */
    hasErrors(): boolean;
    /**
     * Return true if the id or the record is currently in error.
     *
     * @param id The id or record to test.
     * @returns True if the id is in error.
     */
    hasErrorForId(id: string | HRef | HDict): boolean;
}
