/*!
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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 { Readable, Transform } from 'stream';
import { CallOptions } from 'google-gax';
import { JSONOptions, Json, Field, Value } from './codec';
import { google } from '../protos/protos';
export type ResumeToken = string | Uint8Array;
/**
 * @callback RequestFunction
 * @param {string} [resumeToken] The token used to resume getting results.
 * @returns {Stream}
 */
interface RequestFunction {
    (resumeToken?: ResumeToken): Readable;
}
/**
 * @typedef RowOptions
 * @property {boolean} [json=false] Indicates if the Row objects should be
 *     formatted into JSON.
 * @property {JSONOptions} [jsonOptions] JSON options.
 * @property {number} [maxResumeRetries=20] The maximum number of times that the
 *     stream will retry to push data downstream, when the downstream indicates
 *     that it is not ready for any more data. Increase this value if you
 *     experience 'Stream is still not ready to receive data' errors as a
 *     result of a slow writer in your receiving stream.
 * @property {object} [columnsMetadata] An object map that can be used to pass
 * additional properties for each column type which can help in deserializing
 * the data coming from backend. (Eg: We need to pass Proto Function and Enum
 * map to deserialize proto messages and enums, respectively.)
 */
export interface RowOptions {
    json?: boolean;
    jsonOptions?: JSONOptions;
    maxResumeRetries?: number;
    /**
     * An object where column names as keys and custom objects as corresponding
     * values for deserialization. It's specifically useful for data types like
     * protobuf where deserialization logic is on user-specific code. When provided,
     * the custom object enables deserialization of backend-received column data.
     * If not provided, data remains serialized as buffer for Proto Messages and
     * integer for Proto Enums.
     *
     * @example
     * To obtain Proto Messages and Proto Enums as JSON objects, you must supply
     * additional metadata. This metadata should include the protobufjs-cli
     * generated proto message function and enum object. It encompasses the essential
     * logic for proper data deserialization.
     *
     * Eg: To read data from Proto Columns in json format using DQL, you should pass
     * columnsMetadata where key is the name of the column and value is the protobufjs-cli
     * generated proto message function and enum object.
     *
     *     const query = {
     *       sql: `SELECT SingerId,
     *                    FirstName,
     *                    LastName,
     *                    SingerInfo,
     *                    SingerGenre,
     *                    SingerInfoArray,
     *                    SingerGenreArray
     *             FROM Singers
     *             WHERE SingerId = 6`,
     *       columnsMetadata: {
     *         SingerInfo: music.SingerInfo,
     *         SingerInfoArray: music.SingerInfo,
     *         SingerGenre: music.Genre,
     *         SingerGenreArray: music.Genre,
     *       },
     *     };
     */
    columnsMetadata?: object;
    gaxOptions?: CallOptions;
}
/**
 * By default rows are an Array of values in the form of objects containing
 * `name` and `value` properties.
 *
 * If you prefer plain objects, you can use the {@link Row#toJSON} method.
 * NOTE: If you have duplicate field names only the last field will be present.
 *
 * @typedef {Array.<{name: string, value}>} Row
 */
export interface Row extends Array<Field> {
    /**
     * Converts the Row object into a pojo (plain old JavaScript object).
     *
     * @memberof Row
     * @name toJSON
     *
     * @param {JSONOptions} [options] JSON options.
     * @returns {object}
     */
    toJSON(options?: JSONOptions): Json;
}
/**
 * @callback PartialResultStream~rowCallback
 * @param {Row|object} row The row data.
 */
interface RowCallback {
    (row: Row | Json): void;
}
/**
 * @callback PartialResultStream~statsCallback
 * @param {object} stats The result stats.
 */
interface StatsCallback {
    (stats: google.spanner.v1.ResultSetStats): void;
}
/**
 * @callback PartialResultStream~responseCallback
 * @param {object} response The full API response.
 */
interface ResponseCallback {
    (response: google.spanner.v1.PartialResultSet): void;
}
interface ResultEvents {
    addListener(event: 'data', listener: RowCallback): this;
    addListener(event: 'stats', listener: StatsCallback): this;
    addListener(event: 'response', listener: ResponseCallback): this;
    emit(event: 'data', data: Row | Json): boolean;
    emit(event: 'stats', data: google.spanner.v1.ResultSetStats): boolean;
    emit(event: 'response', data: google.spanner.v1.PartialResultSet): boolean;
    on(event: 'data', listener: RowCallback): this;
    on(event: 'stats', listener: StatsCallback): this;
    on(event: 'response', listener: ResponseCallback): this;
    once(event: 'data', listener: RowCallback): this;
    once(event: 'stats', listener: StatsCallback): this;
    once(event: 'response', listener: ResponseCallback): this;
    prependListener(event: 'data', listener: RowCallback): this;
    prependListener(event: 'stats', listener: StatsCallback): this;
    prependListener(event: 'response', listener: ResponseCallback): this;
    prependOnceListener(event: 'data', listener: RowCallback): this;
    prependOnceListener(event: 'stats', listener: StatsCallback): this;
    prependOnceListener(event: 'response', listener: ResponseCallback): this;
}
/**
 * The PartialResultStream transforms partial result set objects into Row
 * objects.
 *
 * @class
 * @extends {Transform}
 *
 * @param {RowOptions} [options] The row options.
 */
export declare class PartialResultStream extends Transform implements ResultEvents {
    private _destroyed;
    private _fields;
    private _options;
    private _pendingValue?;
    private _pendingValueForResume?;
    private _values;
    private _numPushFailed;
    constructor(options?: {});
    /**
     * Destroys the stream.
     *
     * @param {Error} [err] Optional error to destroy stream with.
     */
    destroy(err?: Error): this;
    /**
     * Processes each chunk.
     *
     * @private
     *
     * @param {object} chunk The partial result set.
     * @param {string} encoding Chunk encoding (Not used in object streams).
     * @param {function} next Function to be called upon completion.
     */
    _transform(chunk: google.spanner.v1.PartialResultSet, enc: string, next: Function): void;
    private _tryResume;
    _resetPendingValues(): void;
    /**
     * Manages any chunked values.
     *
     * @private
     *
     * @param {object} chunk The partial result set.
     */
    private _addChunk;
    /**
     * Manages complete values, pushing a completed row into the stream once all
     * values have been received.
     *
     * @private
     *
     * @param {*} value The complete value.
     */
    private _addValue;
    /**
     * Converts an array of values into a row.
     *
     * @private
     *
     * @param {Array.<*>} values The row values.
     * @returns {Row}
     */
    private _createRow;
    /**
     * Attempts to merge chunked values together.
     *
     * @static
     * @private
     *
     * @param {object} type The value type.
     * @param {*} head The head of the combined value.
     * @param {*} tail The tail of the combined value.
     * @returns {Array.<*>}
     */
    static merge(type: google.spanner.v1.Type, head: Value, tail: Value): Value[];
    /**
     * Attempts to merge chunked lists together.
     *
     * @static
     * @private
     *
     * @param {object} type The list type.
     * @param {Array.<*>} head The beginning of the list.
     * @param {Array.<*>} tail The end of the list.
     * @returns {Array.<*>}
     */
    static mergeLists(type: google.spanner.v1.Type, head: Value[], tail: Value[]): Value[];
}
/**
 * Rows returned from queries may be chunked, requiring them to be stitched
 * together. This function returns a stream that will properly assemble these
 * rows, as well as retry after an error. Rows are only emitted if they hit a
 * "checkpoint", which is when a `resumeToken` is returned from the API. Without
 * that token, it's unsafe for the query to be retried, as we wouldn't want to
 * emit the same data multiple times.
 *
 * @private
 *
 * @param {RequestFunction} requestFn The function that makes an API request. It
 *     will receive one argument, `resumeToken`, which should be used however is
 *     necessary to send to the API for additional requests.
 * @param {RowOptions} [options] Options for formatting rows.
 * @returns {PartialResultStream}
 */
export declare function partialResultStream(requestFn: RequestFunction, options?: RowOptions): PartialResultStream;
export {};
