import { action, makeObservable, reaction } from 'mobx';
import { replaceSearchParamsWith } from '../services';
function parseSortString(sortFromUrl) {
    return sortFromUrl.split(',').map((sortExpression) => {
        const [field = '', direction = ''] = sortExpression.split(' ');
        return {
            field: decodeURIComponent(field),
            direction: direction === 'desc' ? 'desc' : 'asc',
        };
    });
}
export class QueryHistoryState {
    constructor(params) {
        this.sortSearchParamName = 'sort';
        this.query = params.query;
        this.history = params.history;
        makeObservable(this, {
            init: action,
            persistAll: action,
            _preInitHistoryPersistence: action,
        });
        this._preInitHistoryPersistence();
    }
    _preInitHistoryPersistence() {
        const { query, history } = this;
        const searchParams = new URLSearchParams(history.location.search);
        Object.values(query.filtersEntries).forEach(([key, filter]) => {
            const valueFromUrl = searchParams.get(key);
            if (valueFromUrl != null) {
                query._initializedFromHistory = true;
                filter.applyFromQueryString(valueFromUrl);
            }
        });
        const sortFromUrl = searchParams.get(this.sortSearchParamName);
        if (sortFromUrl) {
            query._initializedFromHistory = true;
            query.sort.setSortQuery(parseSortString(sortFromUrl), {
                emitChangeEvent: true,
            });
        }
    }
    init() {
        const { history, query } = this;
        const searchParams = new URLSearchParams(history.location.search);
        const disposers = [
            // Apply URL values to dynamically added filters
            reaction(() => query.filtersEntries.map(([key]) => key), () => {
                for (const [key, filter] of query.filtersEntries) {
                    const valueFromUrl = searchParams.get(key);
                    if (valueFromUrl != null) {
                        filter.applyFromQueryString(valueFromUrl);
                    }
                }
            }),
            // Persist all filter/sort changes to URL
            reaction(() => query.filtersKeyHash, () => this.persistAll(), { delay: 250 }),
            reaction(() => query.search.value, () => this.persistAll(), { delay: 250 }),
            reaction(() => query.sort.value.map(({ field, direction }) => ({
                field,
                direction,
            })), () => this.persistAll(), { delay: 250 }),
        ];
        this.persistAll();
        return () => disposers.forEach((d) => d());
    }
    _setFilterValueToSearchParams(searchParams, key, filter) {
        if (!filter.isEmpty) {
            searchParams.set(key, filter.toQueryString);
        }
        else {
            searchParams.delete(key);
        }
    }
    persistAll() {
        const { history, sortSearchParamName, query: { filtersEntries, sort }, } = this;
        replaceSearchParamsWith(history, (searchParams) => {
            for (const [key, filter] of filtersEntries) {
                this._setFilterValueToSearchParams(searchParams, key, filter);
            }
            if (sort.value.length) {
                searchParams.set(sortSearchParamName, sort.value
                    .map(({ field, direction }) => `${encodeURIComponent(field)} ${direction}`)
                    .join(','));
            }
            else {
                searchParams.delete(sortSearchParamName);
            }
        });
    }
}
//# sourceMappingURL=QueryHistoryState.js.map