import * as _angular_core from '@angular/core';
import { OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { BackgroundColorVariant } from '@siemens/element-ng/common';
import { TypeaheadOption } from '@siemens/element-ng/typeahead';
import { TranslatableString } from '@siemens/element-translate-ng/translate';
import { Observable } from 'rxjs';
import { DatepickerInputConfig } from '@siemens/element-ng/datepicker';

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */

type ValidationType = 'string' | 'integer' | 'float' | 'date' | 'date-time';
/**
 * A CriterionValue is the input/output value of the {@link SiFilteredSearchComponent}, containing the user input.
 */
interface CriterionValue {
    /**
     * The mandatory name of a criterion.
     */
    name: string;
    /**
     * This property holds the selected or entered operator of the criterion.
     */
    operator?: string;
    /**
     * The value property holds the selected or entered value/values of the criterion.
     * The value can also be passed as an array of strings. When `multiSelect` is enabled,
     * the items in the value array will be shown as selected values in value input and the typeahead.
     */
    value?: string | string[];
    /** If the criterion was defined as date or date-time this field will contain the value das js Date. */
    dateValue?: Date;
}
/**
 * A CriterionDefinition is the definition of criteria in the {@link SiFilteredSearchComponent}.
 * It defines the type and based this further attributes
 * like multiselect and available options.
 */
interface CriterionDefinition {
    /**
     * The mandatory name of a criterion.
     */
    name: string;
    /**
     * An optional label, which is used in the user interface.
     */
    label?: TranslatableString;
    /**
     * The options provide possible values that the user can select for this criterion.
     */
    options?: OptionType[];
    /**
     * This provides possible operators that the user can select for this criterion.
     */
    operators?: string[];
    /**
     * This provides the value type of the input field.
     */
    validationType?: ValidationType;
    /**
     * Optional configuration object for the datepicker.
     */
    datepickerConfig?: DatepickerInputConfig;
    /**
     * Limit criterion options to the predefined ones.
     */
    strictValue?: boolean;
    /**
     * Limit criterion options to the predefined ones and prevent typing. `onlySelectValue`
     * enforces `strictValue` to true automatically.
     */
    onlySelectValue?: boolean;
    /**
     * Defines whether multi selection of the options is possible in a typeahead. Setting it to `true`
     * enables the checkbox besides the option values. When `multiSelect` is `true`,
     * the value input field will be readonly, allowing user to select the values only from the typeahead.
     */
    multiSelect?: boolean;
}
/**
 * Type for options
 */
type OptionType = string | OptionCriterion;
/**
 * It allows to specify a different value between the one which is rendered
 * and the one which is used for the search.
 */
interface OptionCriterion {
    /**
     * The label to show
     */
    label?: TranslatableString;
    /**
     * The value to use on searching
     */
    value: string;
    /**
     * The icon to be displayed besides value in the typeahead
     */
    iconClass?: string;
    /**
     * Shows whether the option is selected in the multi-select dropdown
     */
    selected?: boolean;
}
/**
 * On search, the filtered search component emits a SearchCriteria object.
 * It consists of all user selected criteria and the free text input value.
 */
interface SearchCriteria {
    /**
     * The selected criteria of the filtered search. Each criteria has a name
     * and a value.
     */
    criteria: CriterionValue[];
    /**
     * Additional unstructured free text, which the user entered in the search.
     */
    value: string;
}
/**
 * Event allows to intercept and change the displayed criteria before shown in typeahead.
 */
interface DisplayedCriteriaEventArgs {
    /**
     * List of criteria names to display in typeahead.
     */
    criteria: string[];
    /**
     * Current search criteria.
     */
    searchCriteria: SearchCriteria;
    /**
     * Interceptor function allows to reduce the list of displayed criteria.
     * @param criteriaNamesToDisplay - list of criteria names to be displayed.
     * @param freeText - indicates whether free text pills are allowed.
     */
    allow(criteriaNamesToDisplay: string[], freeText?: boolean): void;
}

interface InternalCriterionDefinition extends CriterionDefinition {
    label: string;
    translatedLabel: string;
    type?: 'free-text';
}

declare class SiFilteredSearchComponent implements OnInit, OnChanges {
    private static readonly criterionRegex;
    /**
     * Output callback event that provides an object describing the
     * selected criteria and additional filter text.
     */
    readonly doSearch: _angular_core.OutputEmitterRef<SearchCriteria>;
    /**
     * If this is set to `true`, the search triggers for each input (implicit search).
     * By default, the search is triggered when the user submits by pressing the
     * search button or by pressing enter.
     *
     * @defaultValue false
     */
    readonly doSearchOnInputChange: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * In addition to lazy loaded value, you can also lazy load the criteria itself
     */
    readonly lazyCriterionProvider: _angular_core.InputSignal<((typed: string, searchCriteria?: SearchCriteria) => Observable<CriterionDefinition[]>) | undefined>;
    /**
     * In many cases, your application defines the criteria, but the values need
     * to be loaded from a server. In this case you can provide a function that
     * returns the possible criterion options as an Observable.
     */
    readonly lazyValueProvider: _angular_core.InputSignal<((criterionName: string, typed: string | string[]) => Observable<OptionType[]>) | undefined>;
    /**
     * Disable any interactivity.
     *
     * @defaultValue false
     */
    readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Limit criteria to the predefined ones.
     *
     * @defaultValue false
     */
    readonly strictCriterion: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Limit criterion options to the predefined ones. `[strictValue]`
     * enforces `[strictCriterion]` to true automatically.
     *
     * @defaultValue false
     */
    readonly strictValue: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Limit criterion options to the predefined ones and prevent typing. `[onlySelectValue]`
     * enforces `[strictValue]` and `[strictCriterion]` to true automatically.
     *
     * @defaultValue false
     */
    readonly onlySelectValue: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Custom debounce time for lazy loading of criteria data.
     *
     * @defaultValue 500
     */
    readonly lazyLoadingDebounceTime: _angular_core.InputSignal<number>;
    /**
     * Custom debounce time (in mills) to delay the search emission.
     * (Default is 0 as in most cases a users manually triggers a search.
     * Recommended to increase a bit when using doSearchOnInputChange=true)
     *
     * @defaultValue 0
     */
    readonly searchDebounceTime: _angular_core.InputSignal<number>;
    /**
     * The placeholder for input field.
     *
     * @defaultValue ''
     */
    readonly placeholder: _angular_core.InputSignal<string>;
    /**
     * Defines the number of criteria, criteria values and operators visible at once.
     *
     * @defaultValue 10
     */
    readonly optionsInScrollableView: _angular_core.InputSignal<number>;
    /**
     * The current selected search criteria and entered search text.
     *
     * @defaultValue
     * ```
     * { criteria: [], value: '' }
     * ```
     */
    readonly searchCriteria: _angular_core.ModelSignal<SearchCriteria>;
    /**
     * Predefine criteria options.
     *
     * @defaultValue []
     */
    readonly criteria: _angular_core.InputSignal<CriterionDefinition[]>;
    /**
     * Opt-in to search for each criterion only once.
     *
     * @defaultValue false
     */
    readonly exclusiveCriteria: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Limit the number of possible criteria. The default is undefined so that any number of criteria can be used.
     * For example, setting the value to 1 let you only select one criterion that you need to remove before being
     * able to set another one.
     *
     * @defaultValue undefined
     */
    readonly maxCriteria: _angular_core.InputSignal<number | undefined>;
    /**
     * Defines the maximum options within one criterion. The default is 20 and 0 means unlimited.
     *
     * @defaultValue 20
     */
    readonly maxCriteriaOptions: _angular_core.InputSignal<number>;
    /**
     * Search input aria label, Needed by a11y
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_FILTERED_SEARCH.SEARCH:Search`)
     * ```
     */
    readonly searchLabel: _angular_core.InputSignal<TranslatableString>;
    /**
     * Clear button aria label. Needed for a11y
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_FILTERED_SEARCH.CLEAR:Clear`)
     * ```
     */
    readonly clearButtonLabel: _angular_core.InputSignal<TranslatableString>;
    /**
     * The accessible label of the search button.
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_FILTERED_SEARCH.SUBMIT_BUTTON:Submit search`)
     * ```
     */
    readonly submitButtonLabel: _angular_core.InputSignal<TranslatableString>;
    /**
     * Items count text appended to the count in case of multi-selection of values.
     * Translation key, `{{itemCount}}` in the translation will be replaced with the actual value.
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_FILTERED_SEARCH.ITEM_COUNT:{{itemCount}} items`)
     * ```
     */
    readonly itemCountText: _angular_core.InputSignal<TranslatableString>;
    /**
     * Color variant to determine component background
     *
     * @defaultValue 'base-1'
     */
    readonly colorVariant: _angular_core.InputSignal<BackgroundColorVariant>;
    /**
     * Disables the free text search to only use the criterion for filtering.
     *
     * @defaultValue false
     */
    readonly disableFreeTextSearch: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Limit on the number of criteria/criteria value to be displayed by the typeahead
     *
     * @defaultValue 20
     */
    readonly typeaheadOptionsLimit: _angular_core.InputSignal<number>;
    /**
     * By default, the Filtered Search will treat `:` as a special character
     * to submit the current input in the freetext and immediately create a criterion.
     * Use this input to disable this behavior.
     *
     * @defaultValue false
     */
    readonly disableSelectionByColonAndSemicolon: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Criterion definition for free-text pills.
     * When set, free-text values will be added as a pill with this criterion.
     * If not set, free-text pills are disabled.
     *
     * Enabling this will only emit valueChange events when the free-text pill is created.
     * When the text input is blurred and there is text inside, a free-text pill will be created.
     *
     *
     * @experimental
     */
    readonly freeTextCriterion: _angular_core.InputSignal<CriterionDefinition | undefined>;
    /**
     * The value to be shown for creating free-text pills.
     * Use the `{{query}}` placeholder to show the user input in the label.
     *
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_FILTERED_SEARCH.SEARCH_FOR_FREE_TEXT:Search for "{{query}}"`)
     * ```
     *
     * @experimental
     */
    readonly searchForFreeTextLabel: _angular_core.InputSignal<TranslatableString>;
    /**
     * The interceptor is called when the list of criteria is shown as soon as the user starts typing in the input field.
     * The interceptor's {@link DisplayedCriteriaEventArgs.allow} method can be used to filter the list of displayed criteria.
     *
     * **Note:** The interceptor is called as long as the {@link searchCriteria} does not exceed {@link maxCriteria}.
     * Further, the interceptor is not called when using the {@link lazyCriterionProvider}.
     *
     * @example
     * ```
     * <si-filtered-search
     *   [criteria]="[{ name: 'foo', label: 'Foo' }, { name: 'bar', label: 'Bar' }]"
     *   (interceptDisplayedCriteria)="$event.allow(
     *       $event.searchCriteria.criteria.some(s => s.name === 'foo')
     *         ? $event.criteria.filter(c => c !== 'foo')
     *         : $event.criteria
     *     )">
     * </si-filtered-search>
     * ```
     */
    readonly interceptDisplayedCriteria: _angular_core.OutputEmitterRef<DisplayedCriteriaEventArgs>;
    private readonly freeTextInputElement;
    private readonly scrollContainer;
    private readonly valueComponents;
    protected dataSource: Observable<InternalCriterionDefinition[]>;
    protected autoEditCriteria: boolean;
    protected readonly values: _angular_core.WritableSignal<{
        config: InternalCriterionDefinition;
        value: CriterionValue;
    }[]>;
    protected readonly searchValue: _angular_core.WritableSignal<string>;
    /** Internal criteria model */
    protected internalCriterionDefinitions: InternalCriterionDefinition[];
    protected readonly icons: Record<"elementCancel" | "elementSearch", string>;
    /** Used to trigger a renewed search */
    private typeaheadInputChange;
    /** Used to debounce the Search emissions */
    private searchEmitQueue;
    private readonly destroyRef;
    private readonly cdRef;
    private readonly translateService;
    private readonly locale;
    protected readonly allowFreeTextCache: _angular_core.WritableSignal<boolean>;
    private lastEmittedSearchCriteria?;
    protected readonly isStrictOrOnlySelectValue: _angular_core.Signal<boolean>;
    private readonly strictCriterionOrValue;
    private readonly lazyLoadedCriteria;
    private readonly loadedCriteria;
    private readonly internalFreeTextCriterion;
    constructor();
    ngOnChanges(changes: SimpleChanges<this>): void;
    ngOnInit(): void;
    private initCriteria;
    /**
     * Finds a criterion config for a given criterion value.
     * Checks internalCriterionDefinitions first, then freeTextCriterion.
     * Returns undefined if no config was found.
     */
    private findCriterionConfig;
    private initValue;
    /**
     * Deletes all currently selected criteria and effectively resets the filtered search.
     */
    deleteAllCriteria(event?: MouseEvent): void;
    protected deleteCriterion(index: number, event: {
        triggerSearch: boolean;
    } | void): void;
    protected submit(): void;
    protected typeaheadOnSelectCriterion(event: TypeaheadOption): void;
    protected validateCriterionLabel(criterion: InternalCriterionDefinition): boolean;
    /**
     * Converts the internally used data model to the external model.
     * In case options for Criterion is Option[] map to the value from the label.
     */
    private convertToExternalModel;
    private addCriterion;
    /**
     * Get criteria list to be shown in typeahead.
     * @returns list of criteria to be shown in typeahead.
     */
    private getFilteredTypeaheadCriteria;
    private getCriteriaToDisplayFromSubscription;
    protected freeTextFocus(): void;
    protected freeTextBackspace(event: Event): void;
    protected freeTextInput(event: Event): void;
    protected freeTextBlur(): void;
    protected valueChange(value: CriterionValue, criterion: {
        config: InternalCriterionDefinition;
        value: CriterionValue;
    }): void;
    protected focusNext(index: number, event: {
        freeText: string;
    } | void): void;
    private updateAndEmitSearchCriteria;
    private emitChangeEvent;
    protected createFreeTextPill(query: string): void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SiFilteredSearchComponent, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<SiFilteredSearchComponent, "si-filtered-search", never, { "doSearchOnInputChange": { "alias": "doSearchOnInputChange"; "required": false; "isSignal": true; }; "lazyCriterionProvider": { "alias": "lazyCriterionProvider"; "required": false; "isSignal": true; }; "lazyValueProvider": { "alias": "lazyValueProvider"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "strictCriterion": { "alias": "strictCriterion"; "required": false; "isSignal": true; }; "strictValue": { "alias": "strictValue"; "required": false; "isSignal": true; }; "onlySelectValue": { "alias": "onlySelectValue"; "required": false; "isSignal": true; }; "lazyLoadingDebounceTime": { "alias": "lazyLoadingDebounceTime"; "required": false; "isSignal": true; }; "searchDebounceTime": { "alias": "searchDebounceTime"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "optionsInScrollableView": { "alias": "optionsInScrollableView"; "required": false; "isSignal": true; }; "searchCriteria": { "alias": "searchCriteria"; "required": false; "isSignal": true; }; "criteria": { "alias": "criteria"; "required": false; "isSignal": true; }; "exclusiveCriteria": { "alias": "exclusiveCriteria"; "required": false; "isSignal": true; }; "maxCriteria": { "alias": "maxCriteria"; "required": false; "isSignal": true; }; "maxCriteriaOptions": { "alias": "maxCriteriaOptions"; "required": false; "isSignal": true; }; "searchLabel": { "alias": "searchLabel"; "required": false; "isSignal": true; }; "clearButtonLabel": { "alias": "clearButtonLabel"; "required": false; "isSignal": true; }; "submitButtonLabel": { "alias": "submitButtonLabel"; "required": false; "isSignal": true; }; "itemCountText": { "alias": "itemCountText"; "required": false; "isSignal": true; }; "colorVariant": { "alias": "colorVariant"; "required": false; "isSignal": true; }; "disableFreeTextSearch": { "alias": "disableFreeTextSearch"; "required": false; "isSignal": true; }; "typeaheadOptionsLimit": { "alias": "typeaheadOptionsLimit"; "required": false; "isSignal": true; }; "disableSelectionByColonAndSemicolon": { "alias": "disableSelectionByColonAndSemicolon"; "required": false; "isSignal": true; }; "freeTextCriterion": { "alias": "freeTextCriterion"; "required": false; "isSignal": true; }; "searchForFreeTextLabel": { "alias": "searchForFreeTextLabel"; "required": false; "isSignal": true; }; }, { "doSearch": "doSearch"; "searchCriteria": "searchCriteriaChange"; "interceptDisplayedCriteria": "interceptDisplayedCriteria"; }, never, never, true, never>;
}

declare class SiFilteredSearchModule {
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SiFilteredSearchModule, never>;
    static ɵmod: _angular_core.ɵɵNgModuleDeclaration<SiFilteredSearchModule, never, [typeof SiFilteredSearchComponent], [typeof SiFilteredSearchComponent]>;
    static ɵinj: _angular_core.ɵɵInjectorDeclaration<SiFilteredSearchModule>;
}

export { SiFilteredSearchComponent, SiFilteredSearchModule };
export type { CriterionDefinition, CriterionValue, DisplayedCriteriaEventArgs, OptionCriterion, OptionType, SearchCriteria, ValidationType };
