import { Client } from '@elastic/elasticsearch';

interface QueryFilter {
    blocks: QueryFilterBlock[];
}
interface QueryFilterBlock {
    expressions: QueryFilterExpression[];
}
interface QueryFilterExpression {
    field: string;
    operator: "equals" | "notEquals" | "matches" | "contains" | "notContains" | "lessThan" | "greaterThan" | "lessThanOrEquals" | "greaterThanOrEquals" | "incidr" | "notIncidr" | "in" | "notIn";
    value: string | number | boolean | Date | string[];
}
interface QuerySort {
    field: string;
    direction: "asc" | "desc";
}
interface QueryDedup {
    fields: string[];
    sortBy: string | undefined;
    sortDirection: "asc" | "desc" | undefined;
}
interface QueryField {
    name: string;
    alias?: string;
}
interface QueryComp {
    field: string;
    function: string;
    returnField: string;
}
interface QueryAlter {
    field: string;
    func: string;
    parameters: string[];
}
interface QueryConfig {
    key: string;
    value: string;
}
interface LegacyQuery {
    dataset: string;
    fields: QueryField[];
    filters: QueryFilter[];
    alters: QueryAlter[];
    sort: QuerySort[] | null;
    comp: QueryComp[];
    config: QueryConfig[];
    grouping: string | null;
    dedup: QueryDedup | null;
    search: string | null;
    limit: number;
    returnType: "records" | "stats";
}
interface QueryStatement {
    type: "dataset" | "filter" | "fields" | "sort" | "limit" | "comp" | "alter" | "config" | "grouping" | "dedup" | "search";
    filter?: QueryFilter;
    fields?: QueryField[];
    sort?: QuerySort[];
    limit?: number;
    dedup?: QueryDedup;
    alter?: QueryAlter;
    search?: string;
    comp?: QueryComp[];
}
interface Query {
    dataset: string;
    config: QueryConfig[];
    statements: QueryStatement[];
}
interface QueryParsingOptions {
    strictDataset: boolean;
}

declare class QueryExecutor {
    /**
     * Executes the provided query on the given data array.
     *
     * The data array consists of objects with key-value pairs representing the data.
     *
     * If any field or operator is not found in a row of data, an error will be thrown.
     *
     * @param {Query} query The query object containing fields, alters, filters, sort, and limit properties.
     * @param {Array} data The data to be queried, as an array of objects.
     * @returns {Array} The result of the query execution, as an array of objects.
     * @throws {Error} If any field in the query is not found in the data, or an invalid operator is used.
     * @public
     * @static
     */
    static executeQuery(query: Query, data: any[]): any[];
    private static buildElasticsearchExpression;
    private static buildElasticsearchFilter;
    private static buildElasticsearchDedup;
    /**
     * WIP: Executes the provided query on the Elasticsearch client and index.
     *
     * The data array consists of objects with key-value pairs representing the data.
     *
     * If any field or operator is not found in a row of data, an error will be thrown.
     *
     * @deprecated This function is still under development.
     * @param {Query} query The query object containing fields, alters, filters, sort, and limit properties.
     * @param {Array} data The data to be queried, as an Elasticsearch response.
     * @returns {Array} The result of the query execution, as an array of objects.
     * @throws {Error} If any field in the query is not found in the data, or an invalid operator is used.
     * @public
     * @static
     */
    static executeElasticQuery(client: Client, index: string, query: Query): Promise<any[]>;
}

declare class QueryParser {
    /**
     * Parses the provided query string into a Query object.
     *
     * Example query string:
     * `dataset = myDataset | filter price > 100 | sort price desc, name asc | fields name, price as cost, description | limit 10`
     *
     * The returned Query object has properties matching the parsed elements of the query string. If any part of the query string cannot be parsed correctly, an error will be thrown.
     *
     * @param {string} queryString The query string to be parsed.
     * @param {QueryParsingOptions} options Options for parsing the query string.
     * @returns {Query} The parsed query as a Query object.
     * @throws {Error} If any part of the query string cannot be parsed, or if no dataset is specified.
     * @public
     * @static
     */
    static parseQuery(queryString: string, options?: QueryParsingOptions): Query;
}

export { LegacyQuery, Query, QueryAlter, QueryComp, QueryConfig, QueryDedup, QueryExecutor, QueryField, QueryFilter, QueryFilterBlock, QueryFilterExpression, QueryParser, QueryParsingOptions, QuerySort, QueryStatement };
