import { K as KlevuFilterType, a as KlevuDomEvents } from './KlevuSearchSorting-18fcc39a.js';
import { i as isBrowser } from './isBrowser-0ab0def8.js';

/**
 * Filter manager is used to store and handle filters (facets) in the results easily.
 * It can be easily used with applyFilterWithFilterManager() and listFilters() modifiers
 */
class FilterManager {
    /**
     * Manager can be initialized with existing options and sliders
     *
     * @param initialValues initialize manager with values
     */
    constructor(initialValues) {
        var _a;
        this.filters = [];
        this.filters = (_a = initialValues === null || initialValues === void 0 ? void 0 : initialValues.filters) !== null && _a !== void 0 ? _a : [];
    }
    /**
     * @deprecated use filters instead. This doesn't take into account order of options and sliders
     */
    get options() {
        return this.filters.filter((filter) => filter.type === KlevuFilterType.Options);
    }
    /**
     * @deprecated use filters instead. This doesn't take into account order of options and sliders
     */
    get sliders() {
        return this.filters.filter((filter) => filter.type === KlevuFilterType.Slider);
    }
    initFromListFilters(filters) {
        this.filters = filters;
        if (isBrowser()) {
            document.dispatchEvent(new CustomEvent(KlevuDomEvents.FiltersApplied, {
                detail: {
                    filters: this.filters,
                },
            }));
        }
    }
    /**
     * clear current options and sliders
     */
    clear() {
        this.filters = [];
    }
    /**
     * Gets current state of filters
     *
     * @returns current state
     */
    getCurrentState() {
        return {
            filters: this.filters,
        };
    }
    setState(state) {
        this.filters = state.filters;
    }
    /**
     * Function to select filters in filter manager
     *
     * Sends a Dom event on change
     *
     * @param key Key of option
     * @param value value of option to toggle
     */
    toggleOption(key, value) {
        const suboption = this.getOptionByKeyCreateIfNotExists(key, value);
        const prevSeleted = suboption.selected;
        suboption.selected = !suboption.selected;
        if (isBrowser()) {
            document.dispatchEvent(new CustomEvent(KlevuDomEvents.FilterSelectionUpdate, {
                detail: {
                    key,
                    name: value,
                    selected: !prevSeleted,
                },
            }));
        }
    }
    /**
     * Select given option
     *
     * @param key key of filter to select
     * @param value value of option to select
     * @returns
     */
    selectOption(key, value) {
        const suboption = this.getOptionByKeyCreateIfNotExists(key, value);
        suboption.selected = true;
        if (isBrowser()) {
            document.dispatchEvent(new CustomEvent(KlevuDomEvents.FilterSelectionUpdate, {
                detail: {
                    key,
                    name: value,
                    selected: true,
                },
            }));
        }
    }
    /**
     * Deselect given option
     *
     * @param key key of filter to deselect
     * @param value value of option to deselect
     * @returns
     */
    deselectOption(key, value) {
        const suboption = this.getOptionByKeyCreateIfNotExists(key, value);
        suboption.selected = false;
        if (isBrowser()) {
            document.dispatchEvent(new CustomEvent(KlevuDomEvents.FilterSelectionUpdate, {
                detail: {
                    key,
                    name: value,
                    selected: false,
                },
            }));
        }
    }
    /**
     * Sets `selected` key of all options to false
     *
     * @param key Optional key to lmit clearing to one option
     * @returns
     */
    clearOptionSelections(key) {
        if (key) {
            const option = this.filters.find((o) => o.key === key);
            if (option && FilterManager.isKlevuFilterResultOptions(option)) {
                option.options.forEach((o) => (o.selected = false));
            }
            return;
        }
        this.filters.forEach((option) => {
            if (option && FilterManager.isKlevuFilterResultOptions(option)) {
                option.options.forEach((o2) => (o2.selected = false));
            }
        });
        if (isBrowser()) {
            document.dispatchEvent(new CustomEvent(KlevuDomEvents.FilterSelectionUpdate));
        }
    }
    /**
     * Function to update slide in filter manager
     *
     * Sends a Dom event on change
     *
     * @param key Key of slide
     * @param min Min value of slide
     * @param max Max value of slide
     */
    updateSlide(key, min, max) {
        const slideIndex = this.filters.findIndex((s) => s.key === key);
        let slider;
        if (slideIndex === -1) {
            slider = {
                key,
                end: max.toString(),
                start: min.toString(),
                min: min.toString(),
                max: max.toString(),
                label: key,
                type: KlevuFilterType.Slider,
            };
            this.filters.push(slider);
        }
        else if (!FilterManager.isKlevuFilterResultSlider(this.filters[slideIndex])) {
            throw new Error(`Filter ${key} is not a slider filter.`);
        }
        else {
            slider = this.filters[slideIndex];
            slider.start = min.toString();
            slider.end = max.toString();
        }
        if (isBrowser()) {
            document.dispatchEvent(new CustomEvent(KlevuDomEvents.FilterSelectionUpdate, {
                detail: {
                    key: key,
                    name: slider.label,
                    start: min.toString(),
                    end: max.toString(),
                },
            }));
        }
    }
    /**
     * Populate filter manager with filters from Klevu API
     * @returns
     */
    toApplyFilters() {
        const filters = [];
        for (const filter of this.filters) {
            if (FilterManager.isKlevuFilterResultOptions(filter) ||
                FilterManager.isKlevuFilterResultRating(filter)) {
                const selected = filter.options.filter((subOption) => subOption.selected === true);
                if (selected.length === 0) {
                    continue;
                }
                filters.push({
                    key: filter.key,
                    values: selected.map((s) => s.value),
                    settings: {
                        singleSelect: false,
                    },
                });
            }
            else if (FilterManager.isKlevuFilterResultSlider(filter)) {
                if (!filter.start || !filter.end) {
                    continue;
                }
                filters.push({
                    key: filter.key,
                    values: [filter.start, filter.end],
                    settings: {
                        singleSelect: false,
                    },
                });
            }
        }
        return filters;
    }
    /**
     * Get current selection by key
     *
     * @param key
     * @returns
     */
    currentSelection(key) {
        const opt = this.filters.find((o) => o.key === key);
        if (opt &&
            (FilterManager.isKlevuFilterResultOptions(opt) ||
                FilterManager.isKlevuFilterResultRating(opt))) {
            const selectedOptions = opt.options.filter((subOpt) => subOpt.selected === true);
            return selectedOptions.map((s) => s.value);
        }
        if (opt &&
            FilterManager.isKlevuFilterResultSlider(opt) &&
            opt.start &&
            opt.end) {
            return [opt.start, opt.end];
        }
        return undefined;
    }
    /**
     * Changes current selection of filters to a URL param string
     *
     * @returns string of URL params
     */
    toURLParams() {
        const params = new URLSearchParams();
        for (const filter of this.filters) {
            if (FilterManager.isKlevuFilterResultOptions(filter) ||
                FilterManager.isKlevuFilterResultRating(filter)) {
                const selected = filter.options.filter((subOption) => subOption.selected === true);
                if (selected.length === 0) {
                    continue;
                }
                params.append(`o_${filter.key}`, selected.map((s) => s.value).join(","));
            }
            else if (FilterManager.isKlevuFilterResultSlider(filter)) {
                if (!filter.start || !filter.end) {
                    continue;
                }
                params.append(`s_${filter.key}`, `${filter.start}-${filter.end}`);
            }
        }
        return params.toString();
    }
    /**
     * Set current selection of filters from a URL param string
     *
     * @param params URLSearchParams to read from
     */
    readFromURLParams(params) {
        this.clearOptionSelections();
        for (const [key, value] of params.entries()) {
            if (key.startsWith("o")) {
                const optionKey = key.substring(2);
                value.split(",").forEach((v) => this.selectOption(optionKey, v));
            }
            else if (key.startsWith("s")) {
                const sliderKey = key.substring(2);
                this.updateSlide(sliderKey, parseFloat(value.split("-")[0]), parseFloat(value.split("-")[1]));
            }
        }
    }
    /**
     * Quickly get all selected options and sliders
     *
     * @returns Array of selected filters, with key, label, type and value
     */
    selectedFilters() {
        const selectedFilters = [];
        for (const filter of this.filters) {
            if (FilterManager.isKlevuFilterResultOptions(filter) ||
                FilterManager.isKlevuFilterResultRating(filter)) {
                const selected = filter.options.filter((subOption) => subOption.selected === true);
                if (selected.length === 0) {
                    continue;
                }
                for (const option of selected) {
                    selectedFilters.push({
                        key: filter.key,
                        label: filter.label,
                        type: filter.type,
                        value: option.value,
                    });
                }
            }
            else if (FilterManager.isKlevuFilterResultSlider(filter)) {
                if (!filter.start || !filter.end) {
                    continue;
                }
                selectedFilters.push({
                    key: filter.key,
                    label: filter.label,
                    type: filter.type,
                    value: `${filter.start}-${filter.end}`,
                });
            }
        }
        return selectedFilters;
    }
    /**
     * Get option by key and sub option name. If doesn't exist, create it.
     *
     * @param key
     * @returns
     */
    getOptionByKeyCreateIfNotExists(key, value) {
        const optionIndex = this.filters.findIndex((o) => o.key === key);
        let option;
        if (optionIndex === -1) {
            option = {
                key,
                label: key,
                options: [],
                type: KlevuFilterType.Options,
            };
            this.filters.push(option);
        }
        else if (!FilterManager.isKlevuFilterResultOptions(this.filters[optionIndex]) &&
            !FilterManager.isKlevuFilterResultRating(this.filters[optionIndex])) {
            throw new Error(`Filter ${key} is not an option filter.`);
        }
        else {
            option = this.filters[optionIndex];
        }
        const subOptionIndex = option.options.findIndex((o) => o.value === value);
        if (subOptionIndex === -1) {
            option.options.push({
                count: 1,
                name: value,
                selected: false,
                value: value,
            });
            return option.options[option.options.length - 1];
        }
        return option.options[subOptionIndex];
    }
    /**
     * Is given variable a slider filter
     * @param filter
     * @returns
     */
    static isKlevuFilterResultSlider(filter) {
        return filter.type === KlevuFilterType.Slider;
    }
    /**
     * Is given variable an option filter
     * @param filter
     * @returns
     */
    static isKlevuFilterResultOptions(filter) {
        return filter.type === KlevuFilterType.Options;
    }
    /**
     * Is given variable an rating filter
     * @param filter
     * @returns
     */
    static isKlevuFilterResultRating(filter) {
        return filter.type === KlevuFilterType.Rating;
    }
}

export { FilterManager as F };

//# sourceMappingURL=filterManager-5c146ecb.js.map