import { addEventListener, TaskState, WixPatternsError, } from '@wix/bex-core';
import { ViewsState } from './ViewsState';
import { action, computed, makeObservable, runInAction } from 'mobx';
import { CollectionViewsStateBIReporter } from './CollectionViewsStateBIReporter';
import { EventEmitter } from 'events';
import { indexOfCompareFn } from './indexOfCompareFn';
import { CollectionViewsQueryCompareHelper } from './CollectionViewsQueryCompareHelper';
import { ViewsHistoryState } from './ViewsHistoryState';
export class CollectionViewsState {
    constructor(params) {
        this.initTask = new TaskState();
        this.emitter = new EventEmitter();
        this.table = params.table;
        this.onDeleteView = params.onDeleteView;
        this.onSaveViewChanges = params.onSaveViewChanges;
        this.onSaveView = params.onSaveView;
        this.onRenameView = params.onRenameView;
        this.onSetAsDefaultView = params.onSetAsDefaultView;
        this.learnMoreLink = params.learnMoreLink;
        this.viewNamePlaceholder = params.viewNamePlaceholder;
        this.views = new ViewsState({
            oldNamespace: this.table.namespace,
            container: params.container,
            presets: params.presets,
            fqdn: this.table.collection.queryName,
            allItemsViewProps: params.allItemsViewProps,
            reportBI: this.table.reportBi,
        });
        this.views._migrateOrdersViews = (viewsState) => {
            this.table.collection._migrateOrdersViews?.(viewsState);
        };
        this.views._fixMissingContactsViews = (viewsState) => {
            this.table.collection._fixMissingContactsViews?.(viewsState);
        };
        this.queryCompareHelper = new CollectionViewsQueryCompareHelper({
            table: this.table,
            collectionViews: this,
        });
        this.viewsStateBIReporter = new CollectionViewsStateBIReporter({
            reportBI: this.table.reportBi,
            collectionViewState: this,
        });
        makeObservable(this, {
            _setSelectedViewToCollectionQuery: action.bound,
            _onSelectViewAndRefresh: action.bound,
            _selectInitialView: action.bound,
            isViewChanged: computed,
            currentViewColumns: computed,
            currentViewColumnsOrDefaultColumns: computed,
        });
    }
    get isViewChanged() {
        const { views: { currentView }, } = this;
        return (!currentView ||
            this.queryCompareHelper.isSelectedColumnsChanged ||
            this.queryCompareHelper.isSortChanged ||
            this.queryCompareHelper.isFiltersChanged);
    }
    get _doNotWaitForViewsExperimentEnabled() {
        const { table: { container: { experiments, internalExperiments }, }, } = this;
        return (internalExperiments?.enabled('specs.cairo.doNotWaitForViews') ||
            experiments.enabled('specs.cairo.stores.doNotWaitForViews'));
    }
    init() {
        const { views, initTask, table: { collection, container: { history }, }, } = this;
        if (this._doNotWaitForViewsExperimentEnabled) {
            this._selectInitialView(views._getAllItemsAndPresetViews());
        }
        const disposers = [
            addEventListener(collection.hooks, 'beforeInitialFetch', action(async () => {
                if (!this._doNotWaitForViewsExperimentEnabled &&
                    !collection.query._initializedFromHistory) {
                    await this.initTask.status.promise?.catch(() => { });
                }
            })),
            views.init(),
            ...this._subscribeOnSelectView(),
            ...this._subscribeOnViewAction(),
            this.viewsStateBIReporter.init(),
            new ViewsHistoryState({
                views: this.views,
                history,
            }).init(),
        ];
        initTask.runOnce(async () => {
            await views.initTask.status.promise;
            runInAction(() => {
                if (this._selectInitialView(views.collection.result.items)) {
                    // when not waiting for views, we need to refresh the collection as the initialView after views loaded might have changed the query
                    if (this._doNotWaitForViewsExperimentEnabled) {
                        this.table.collection.clearResultAndMoveToStart();
                    }
                }
            });
        });
        return () => {
            disposers.forEach((disposer) => disposer());
        };
    }
    _selectInitialView(items) {
        const { views, table: { collection }, } = this;
        if (this.views.currentView) {
            return;
        }
        const initialSelectItem = views._getInitialSelectItem(items);
        if (initialSelectItem == null) {
            return;
        }
        if (!views._initialViewIdFromUrl &&
            collection.query._initializedFromHistory) {
            return;
        }
        const view = views.getView(initialSelectItem.id);
        views.currentView = view ?? null;
        if (!collection.query._initializedFromHistory) {
            this._setSelectedViewToCollectionQuery();
            return true;
        }
    }
    _subscribeOnViewAction() {
        const { views } = this;
        return [
            addEventListener(views.events, 'undoAction', this.viewsStateBIReporter.undoActionBI.bind(this.viewsStateBIReporter)),
            addEventListener(views.events, 'tryAgainAction', this.viewsStateBIReporter.tryAgainBI.bind(this.viewsStateBIReporter)),
            addEventListener(views.events, 'errorAction', this.viewsStateBIReporter.errorBI.bind(this.viewsStateBIReporter)),
        ];
    }
    _subscribeOnSelectView() {
        const { views } = this;
        return [
            addEventListener(views.events, 'selectAndRefresh', action(this._onSelectViewAndRefresh)),
        ];
    }
    _onSelectViewAndRefresh(needFiltersReset = true) {
        if (!needFiltersReset) {
            return;
        }
        const { table: { collection }, } = this;
        const { query } = collection;
        this._setSelectedViewToCollectionQuery();
        query.events.emit('refresh');
    }
    get currentViewColumns() {
        const { views, table } = this;
        const { columns, customColumnsState } = table;
        const { currentView } = views;
        const viewSelectedColumns = currentView?.selectedColumns;
        if (!viewSelectedColumns?.length) {
            return null;
        }
        const selectedColumnsToSet = columns.map(({ id, hideable, hiddenFromCustomColumnsSelection }) => ({
            id,
            isSelected: viewSelectedColumns.some((c) => c.id === id && c.isSelected !== false) ||
                !hideable ||
                hiddenFromCustomColumnsSelection === true,
        }));
        return customColumnsState?.dragAndDrop
            ? selectedColumnsToSet.sort(indexOfCompareFn(viewSelectedColumns, (e) => e?.id))
            : selectedColumnsToSet;
    }
    get currentViewColumnsOrDefaultColumns() {
        return this.currentViewColumns ?? this.table.selectedColumns.defaultValue;
    }
    _setSelectedViewToCollectionQuery() {
        const { views, table } = this;
        const { selectedColumns, collection } = table;
        const { currentView } = views;
        const { query } = collection;
        query.resetFilters();
        if (currentView?.filters) {
            Object.entries(currentView.filters).forEach(([filterName, filter]) => {
                const queryFilter = query.filters[filterName];
                if (queryFilter && queryFilter.value !== filter?.value) {
                    queryFilter.setValue(queryFilter.decode(filter?.value));
                }
            });
        }
        query.resetSorting();
        if (currentView?.sortDirections && currentView.sortDirections.length > 0) {
            query.sort.setSortQuery(currentView.sortDirections.map((sortInView) => ({
                field: sortInView.columnId,
                direction: sortInView.direction === 'Ascending' ? 'asc' : 'desc',
            })), { emitChangeEvent: true });
        }
        else {
            query.resetSorting({ emitChangeEvent: true });
        }
        if (this.currentViewColumns) {
            selectedColumns.setValue(this.currentViewColumns);
        }
        else {
            selectedColumns.reset();
        }
        query.setExtra(currentView?.extra);
    }
    async deleteView(view) {
        try {
            const viewToDelete = view ?? this.views.currentView;
            if (!viewToDelete) {
                return;
            }
            this.viewsStateBIReporter.deleteViewSelectedBI();
            this.onDeleteView?.(viewToDelete);
            await this.views.deleteView(viewToDelete);
            this.viewsStateBIReporter.deleteViewBI(viewToDelete);
        }
        catch (e) {
            throw new WixPatternsError({
                originalException: e,
                errorCode: 'DeleteViewFailed',
            });
        }
    }
    async saveViewChanges() {
        this.viewsStateBIReporter.saveViewChangesSelectedBI();
        const oldView = this.views.currentView
            ? { ...this.views.currentView }
            : undefined;
        const newView = await this.views.saveViewChanges(this.queryCompareHelper.currentViewBase);
        if (newView) {
            this.onSaveViewChanges?.(newView);
            this.viewsStateBIReporter.saveViewChangesBI(newView, oldView);
        }
    }
    sendSaveNewViewSelectedBI() {
        this.viewsStateBIReporter.saveNewViewSelectedBI();
    }
    async saveNewView(name) {
        try {
            const newView = await this.views.saveView({
                newView: this.views.createNewView(name, this.queryCompareHelper.currentViewBase),
                isNew: true,
                oldViewId: this.views.currentView?.id,
            });
            this.onSaveView?.(newView);
            this.viewsStateBIReporter.saveNewViewBI(newView);
        }
        catch (err) {
            throw new WixPatternsError({
                errorCode: 'SaveViewFailed',
                originalException: err,
            });
        }
    }
    sendRenameViewSelectedBI() {
        this.viewsStateBIReporter.renameViewSelectedBI();
    }
    async renameView(name) {
        try {
            if (!this.views.currentView) {
                return;
            }
            const oldName = this.views.currentView.name;
            const newView = await this.views.renameView({ ...this.views.currentView, name }, this.views.currentView?.name ?? '');
            this.onRenameView?.(newView);
            this.viewsStateBIReporter.renameViewBI(newView, oldName);
        }
        catch (e) {
            throw new WixPatternsError({
                originalException: e,
                errorCode: 'RenameViewFailed',
            });
        }
    }
    async setAsDefaultView() {
        try {
            if (!this.views.currentView) {
                return;
            }
            const isDefault = this.views.defaultViewId !== this.views.currentView.id;
            this.viewsStateBIReporter.setAsDefaultViewSelectedBI(isDefault);
            const newView = await this.views.setAsDefaultView(this.views.currentView, isDefault);
            this.onSetAsDefaultView?.(newView, isDefault);
            this.viewsStateBIReporter.setAsDefaultViewBI(isDefault, newView);
        }
        catch (e) {
            throw new WixPatternsError({
                originalException: e,
                errorCode: 'SetAsDefaultViewFailed',
            });
        }
    }
}
//# sourceMappingURL=CollectionViewsState.js.map