/**
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import ResultSummary from './result-summary';
import Record, { RecordShape } from './record';
import { Query, PeekableAsyncIterator } from './types';
import { observer, connectionHolder } from './internal';
import { NumberOrInteger } from './graph-types';
import Integer from './integer';
/**
 * The query result is the combination of the {@link ResultSummary} and
 * the array {@link Record[]} produced by the query
 */
interface QueryResult<R extends RecordShape = RecordShape> {
    records: Array<Record<R>>;
    summary: ResultSummary;
}
/**
 * Interface to observe updates on the Result which is being produced.
 *
 */
interface ResultObserver<R extends RecordShape = RecordShape> {
    /**
     * Receive the keys present on the record whenever this information is available
     *
     * @param {string[]} keys The keys present on the {@link Record}
     */
    onKeys?: (keys: string[]) => void;
    /**
     * Receive the each record present on the {@link @Result}
     * @param {Record} record The {@link Record} produced
     */
    onNext?: (record: Record<R>) => void;
    /**
     * Called when the result is fully received
     * @param {ResultSummary} summary The result summary
     */
    onCompleted?: (summary: ResultSummary) => void;
    /**
     * Called when some error occurs during the result processing or query execution
     * @param {Error} error The error ocurred
     */
    onError?: (error: Error) => void;
}
/**
 * A stream of {@link Record} representing the result of a query.
 * Can be consumed eagerly as {@link Promise} resolved with array of records and {@link ResultSummary}
 * summary, or rejected with error that contains {@link string} code and {@link string} message.
 * Alternatively can be consumed lazily using {@link Result#subscribe} function.
 * @access public
 */
declare class Result<R extends RecordShape = RecordShape> implements Promise<QueryResult<R>> {
    private readonly _stack;
    private readonly _streamObserverPromise;
    private _p;
    private readonly _query;
    private readonly _parameters;
    private readonly _connectionHolder;
    private _keys;
    private _summary;
    private _error;
    private readonly _watermarks;
    /**
     * Inject the observer to be used.
     * @constructor
     * @access private
     * @param {Promise<observer.ResultStreamObserver>} streamObserverPromise
     * @param {mixed} query - Cypher query to execute
     * @param {Object} parameters - Map with parameters to use in query
     * @param {ConnectionHolder} connectionHolder - to be notified when result is either fully consumed or error happened.
     */
    constructor(streamObserverPromise: Promise<observer.ResultStreamObserver>, query: Query, parameters?: any, connectionHolder?: connectionHolder.ConnectionHolder, watermarks?: {
        high: number;
        low: number;
    });
    /**
     * Returns a promise for the field keys.
     *
     * *Should not be combined with {@link Result#subscribe} function.*
     *
     * @public
     * @returns {Promise<string[]>} - Field keys, in the order they will appear in records.
     }
     */
    keys(): Promise<string[]>;
    /**
     * Returns a promise for the result summary.
     *
     * *Should not be combined with {@link Result#subscribe} function.*
     *
     * @public
     * @returns {Promise<ResultSummary<T>>} - Result summary.
     *
     */
    summary<T extends NumberOrInteger = Integer>(): Promise<ResultSummary<T>>;
    /**
     * Create and return new Promise
     *
     * @private
     * @return {Promise} new Promise.
     */
    private _getOrCreatePromise;
    /**
     * Provides a async iterator over the records in the result.
     *
     * *Should not be combined with {@link Result#subscribe} or {@link Result#then} functions.*
     *
     * @public
     * @returns {PeekableAsyncIterator<Record<R>, ResultSummary>} The async iterator for the Results
     */
    [Symbol.asyncIterator](): PeekableAsyncIterator<Record<R>, ResultSummary>;
    /**
     * Waits for all results and calls the passed in function with the results.
     *
     * *Should not be combined with {@link Result#subscribe} function.*
     *
     * @param {function(result: {records:Array<Record>, summary: ResultSummary})} onFulfilled - function to be called
     * when finished.
     * @param {function(error: {message:string, code:string})} onRejected - function to be called upon errors.
     * @return {Promise} promise.
     */
    then<TResult1 = QueryResult<R>, TResult2 = never>(onFulfilled?: ((value: QueryResult<R>) => TResult1 | PromiseLike<TResult1>) | null, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
    /**
     * Catch errors when using promises.
     *
     * *Should not be combined with {@link Result#subscribe} function.*
     *
     * @param {function(error: Neo4jError)} onRejected - Function to be called upon errors.
     * @return {Promise} promise.
     */
    catch<TResult = never>(onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<QueryResult<R> | TResult>;
    /**
     * Called when finally the result is done
     *
     * *Should not be combined with {@link Result#subscribe} function.*
     * @param {function()|null} onfinally - function when the promise finished
     * @return {Promise} promise.
     */
    [Symbol.toStringTag]: string;
    finally(onfinally?: (() => void) | null): Promise<QueryResult<R>>;
    /**
     * Stream records to observer as they come in, this is a more efficient method
     * of handling the results, and allows you to handle arbitrarily large results.
     *
     * @param {Object} observer - Observer object
     * @param {function(keys: string[])} observer.onKeys - handle stream head, the field keys.
     * @param {function(record: Record)} observer.onNext - handle records, one by one.
     * @param {function(summary: ResultSummary)} observer.onCompleted - handle stream tail, the result summary.
     * @param {function(error: {message:string, code:string})} observer.onError - handle errors.
     * @return {void}
     */
    subscribe(observer: ResultObserver<R>): void;
    /**
     * Check if this result is active, i.e., neither a summary nor an error has been received by the result.
     * @return {boolean} `true` when neither a summary or nor an error has been received by the result.
     */
    isOpen(): boolean;
    /**
     * Stream records to observer as they come in, this is a more efficient method
     * of handling the results, and allows you to handle arbitrarily large results.
     *
     * @access private
     * @param {ResultObserver} observer The observer to send records to.
     * @param {boolean} paused The flag to indicate if the stream should be started paused
     * @returns {Promise<observer.ResultStreamObserver>} The result stream observer.
     */
    _subscribe(observer: ResultObserver, paused?: boolean): Promise<observer.ResultStreamObserver>;
    /**
     * Decorates the ResultObserver with the necessary methods.
     *
     * @access private
     * @param {ResultObserver} observer The ResultObserver to decorate.
     * @returns The decorated result observer
     */
    _decorateObserver(observer: ResultObserver): ResultObserver;
    /**
     * Signals the stream observer that the future records should be discarded on the server.
     *
     * @protected
     * @since 4.0.0
     * @returns {void}
     */
    _cancel(): void;
    /**
     * @access private
     * @param metadata
     * @returns
     */
    private _releaseConnectionAndGetSummary;
    /**
     * @access private
     */
    private _createQueuedResultObserver;
}
export default Result;
export type { QueryResult, ResultObserver };
