interface CommonProperties {
    path?: number[];
    id?: string;
    disabled?: boolean;
}
type RuleType<F extends string = string, O extends string = string, V = any, C extends string = string> = CommonProperties & {
    field: F;
    operator: O;
    value: V;
    valueSource?: ValueSource;
    /**
     * Only used when adding a rule to a query that uses independent combinators
     */
    combinatorPreceding?: C;
};
type RuleGroupType<R extends RuleType = RuleType, C extends string = string> = CommonProperties & {
    combinator: C;
    rules: RuleGroupArray<RuleGroupType<R, C>, R>;
    not?: boolean;
};
type RuleGroupArray<RG extends RuleGroupType = RuleGroupType, R extends RuleType = RuleType> = (R | RG)[];
type DefaultRuleGroupArray = RuleGroupArray<DefaultRuleGroupType, DefaultRuleType>;
type DefaultRuleGroupType = RuleGroupType<DefaultRuleType, DefaultCombinatorNameExtended> & {
    rules: DefaultRuleGroupArray;
};
type DefaultRuleType = RuleType<string, DefaultOperatorName>;
type DefaultCombinatorName = 'and' | 'or';
type DefaultCombinatorNameExtended = DefaultCombinatorName | 'xor';
type DefaultOperatorName = '=' | '!=' | '<' | '>' | '<=' | '>=' | 'contains' | 'beginsWith' | 'endsWith' | 'doesNotContain' | 'doesNotBeginWith' | 'doesNotEndWith' | 'null' | 'notNull' | 'in' | 'notIn' | 'between' | 'notBetween';

type MAXIMUM_ALLOWED_BOUNDARY = 80;
type MappedTuple<Tuple extends Array<unknown>, Result extends Array<unknown> = [], Count extends ReadonlyArray<number> = []> = Count['length'] extends MAXIMUM_ALLOWED_BOUNDARY ? Result : Tuple extends [] ? [] : Result extends [] ? MappedTuple<Tuple, Tuple, [...Count, 1]> : MappedTuple<Tuple, Result | [...Result, ...Tuple], [...Count, 1]>;

type RuleGroupTypeIC<R extends RuleType = RuleType, C extends string = string> = Omit<RuleGroupType<R, C>, 'combinator' | 'rules'> & {
    rules: RuleGroupICArray<RuleGroupTypeIC<R, C>, R, C>;
    /**
     * Only used when adding a rule to a query that uses independent combinators
     */
    combinatorPreceding?: C;
};
type RuleGroupTypeAny = RuleGroupType | RuleGroupTypeIC;
type RuleGroupICArray<RG extends RuleGroupTypeIC = RuleGroupTypeIC, R extends RuleType = RuleType, C extends string = string> = [R | RG] | [R | RG, ...MappedTuple<[C, R | RG]>] | ((R | RG)[] & {
    length: 0;
});
type DefaultRuleGroupICArray = RuleGroupICArray<DefaultRuleGroupTypeIC, DefaultRuleType, DefaultCombinatorName>;
interface DefaultRuleGroupTypeIC extends RuleGroupTypeIC {
    rules: DefaultRuleGroupICArray;
}

interface ValidationResult {
    valid: boolean;
    reasons?: any[];
}
type ValidationMap = Record<string, boolean | ValidationResult>;
type QueryValidator = (query: RuleGroupTypeAny) => boolean | ValidationMap;
type RuleValidator = (rule: RuleType) => boolean | ValidationResult;

type Classname = string | string[] | Record<string, any>;
type ValueSource = 'value' | 'field';
type ValueEditorType = 'text' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'switch' | 'multiselect' | null;
type ValueSources = ['value'] | ['value', 'field'] | ['field', 'value'] | ['field'];
interface Option<N extends string = string> {
    name: N;
    label: string;
    [x: string]: any;
}
type OptionGroup<Opt extends Option = Option> = {
    label: string;
    options: Opt[];
};
type OptionList<Opt extends Option = Option> = Opt[] | OptionGroup<Opt>[];
interface HasOptionalClassName {
    className?: Classname;
}
interface Field<FieldName extends string = string, OperatorName extends string = string, ValueName extends string = string, OperatorObj extends Option = Option<OperatorName>, ValueObj extends Option = Option<ValueName>> extends Option<FieldName>, HasOptionalClassName {
    id?: string;
    operators?: OptionList<OperatorObj>;
    valueEditorType?: ValueEditorType | ((operator: OperatorName) => ValueEditorType);
    valueSources?: ValueSources | ((operator: OperatorName) => ValueSources);
    inputType?: string | null;
    values?: OptionList<ValueObj>;
    defaultOperator?: OperatorName;
    defaultValue?: any;
    placeholder?: string;
    validator?: RuleValidator;
    comparator?: string | ((f: Field, operator: string) => boolean);
}

export { DefaultRuleGroupType as D, Field as F, OptionList as O, QueryValidator as Q, RuleType as R, ValueSource as V, RuleGroupTypeAny as a, DefaultRuleGroupTypeIC as b, ValueSources as c, RuleGroupType as d, RuleGroupTypeIC as e };
