/**
 * Copyright (c) 2020-present, Goldman Sachs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH, } from '@finos/legend-application';
import { QuerySearchSpecification, GRAPH_MANAGER_EVENT, QuerySearchSortBy, } from '@finos/legend-graph';
import { ActionState, assertErrorThrown, guaranteeNonNullable, LogEvent, } from '@finos/legend-shared';
import { makeObservable, observable, action, flow } from 'mobx';
export const QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT = 50;
export const QUERY_LOADER_DEFAULT_QUERY_SEARCH_LIMIT = 10;
export var SORT_BY_OPTIONS;
(function (SORT_BY_OPTIONS) {
    SORT_BY_OPTIONS["SORT_BY_CREATE"] = "Last Created";
    SORT_BY_OPTIONS["SORT_BY_VIEW"] = "Last Viewed";
    SORT_BY_OPTIONS["SORT_BY_UPDATE"] = "Last Updated";
})(SORT_BY_OPTIONS || (SORT_BY_OPTIONS = {}));
export class QueryLoaderState {
    applicationStore;
    graphManager;
    searchQueriesState = ActionState.create();
    renameQueryState = ActionState.create();
    deleteQueryState = ActionState.create();
    previewQueryState = ActionState.create();
    decorateSearchSpecification;
    loadQuery;
    fetchDefaultQueries;
    generateDefaultQueriesSummaryText;
    isReadOnly;
    onQueryRenamed;
    onQueryDeleted;
    handleFetchDefaultQueriesFailure;
    queryBuilderState;
    searchText = '';
    showCurrentUserQueriesOnly = false; // TODO: if we start having more native filters, we should make them part of `extraFilters`
    extraFilters = new Map();
    extraFilterOptions = [];
    extraQueryFilterOptionsRelatedToTemplateQuery = [];
    queries = [];
    curatedTemplateQuerySpecifications = [];
    isQueryLoaderDialogOpen = false;
    isCuratedTemplateToggled = false;
    showingDefaultQueries = true;
    showPreviewViewer = false;
    queryPreviewContent;
    sortBy = SORT_BY_OPTIONS.SORT_BY_VIEW;
    constructor(applicationStore, graphManager, options) {
        makeObservable(this, {
            isQueryLoaderDialogOpen: observable,
            queryPreviewContent: observable,
            showingDefaultQueries: observable,
            queries: observable,
            showCurrentUserQueriesOnly: observable,
            showPreviewViewer: observable,
            searchText: observable,
            isCuratedTemplateToggled: observable,
            curatedTemplateQuerySpecifications: observable,
            sortBy: observable,
            setSortBy: action,
            setSearchText: action,
            setQueryLoaderDialogOpen: action,
            setQueries: action,
            setShowCurrentUserQueriesOnly: action,
            setShowPreviewViewer: action,
            setIsCuratedTemplateToggled: action,
            searchQueries: flow,
            getPreviewQueryContent: flow,
            deleteQuery: flow,
            renameQuery: flow,
            initialize: flow,
        });
        this.applicationStore = applicationStore;
        this.graphManager = graphManager;
        this.loadQuery = options.loadQuery;
        this.fetchDefaultQueries = options.fetchDefaultQueries;
        this.generateDefaultQueriesSummaryText =
            options.generateDefaultQueriesSummaryText;
        this.decorateSearchSpecification = options.decorateSearchSpecification;
        this.isReadOnly = options.isReadOnly;
        this.onQueryRenamed = options.onQueryRenamed;
        this.onQueryDeleted = options.onQueryDeleted;
        this.handleFetchDefaultQueriesFailure =
            options.handleFetchDefaultQueriesFailure;
    }
    setIsCuratedTemplateToggled(val) {
        this.isCuratedTemplateToggled = val;
    }
    setSortBy(val) {
        this.sortBy = val;
    }
    getQuerySearchSortBy(sortByValue) {
        switch (sortByValue) {
            case SORT_BY_OPTIONS.SORT_BY_CREATE:
                return QuerySearchSortBy.SORT_BY_CREATE;
            case SORT_BY_OPTIONS.SORT_BY_UPDATE:
                return QuerySearchSortBy.SORT_BY_UPDATE;
            case SORT_BY_OPTIONS.SORT_BY_VIEW:
                return QuerySearchSortBy.SORT_BY_VIEW;
            default:
                return undefined;
        }
    }
    setSearchText(val) {
        this.searchText = val;
    }
    setQueryLoaderDialogOpen(val) {
        this.isQueryLoaderDialogOpen = val;
    }
    setQueries(val) {
        this.queries = val;
    }
    // search query using search specification
    canPerformAdvancedSearch(searchText) {
        return !(searchText.length < DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH &&
            !this.showCurrentUserQueriesOnly &&
            Array.from(this.extraFilters.values()).every((value) => value === false));
    }
    setShowPreviewViewer(val) {
        this.showPreviewViewer = val;
    }
    setShowCurrentUserQueriesOnly(val) {
        this.showCurrentUserQueriesOnly = val;
    }
    reset() {
        this.setShowCurrentUserQueriesOnly(false);
        this.setIsCuratedTemplateToggled(false);
    }
    *initialize(queryBuilderState) {
        this.queryBuilderState = queryBuilderState;
        this.extraFilterOptions = this.applicationStore.pluginManager
            .getApplicationPlugins()
            .flatMap((plugin) => plugin.getExtraLoadQueryFilterOptions?.() ?? []);
        this.extraQueryFilterOptionsRelatedToTemplateQuery =
            this.applicationStore.pluginManager
                .getApplicationPlugins()
                .flatMap((plugin) => plugin
                .getQueryFilterOptionsRelatedToTemplateQuery?.()(guaranteeNonNullable(this.queryBuilderState))
                .flat() ?? []);
        const extraFilters = this.extraFilterOptions.map((filterOption) => filterOption.label(guaranteeNonNullable(this.queryBuilderState)));
        extraFilters.forEach((filter) => filter && this.extraFilters.set(filter, false));
        this.curatedTemplateQuerySpecifications =
            this.applicationStore.pluginManager
                .getApplicationPlugins()
                .flatMap((plugin) => plugin.getCuratedTemplateQuerySpecifications?.() ?? []);
    }
    *searchQueries(searchText) {
        if (!this.canPerformAdvancedSearch(searchText)) {
            // if no search text is specified, use fetch the default queries
            if (!searchText) {
                this.showingDefaultQueries = true;
                this.searchQueriesState.inProgress();
                this.queries = [];
                try {
                    if (!this.fetchDefaultQueries) {
                        return;
                    }
                    this.queries = (yield this.fetchDefaultQueries()).sort((a, b) => a.name.localeCompare(b.name));
                    this.searchQueriesState.pass();
                }
                catch (error) {
                    this.searchQueriesState.fail();
                    assertErrorThrown(error);
                    this.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.GET_QUERY_FAILURE), error);
                    this.handleFetchDefaultQueriesFailure?.();
                }
            }
            // skip otherwise
            return;
        }
        // search using the search term
        this.showingDefaultQueries = false;
        this.searchQueriesState.inProgress();
        try {
            let searchSpecification = QuerySearchSpecification.createDefault(searchText);
            searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT + 1;
            searchSpecification.showCurrentUserQueriesOnly =
                this.showCurrentUserQueriesOnly;
            const querySearchSortBy = this.getQuerySearchSortBy(this.sortBy);
            if (querySearchSortBy) {
                searchSpecification.sortByOption = querySearchSortBy;
            }
            if (this.queryBuilderState) {
                Array.from(this.extraFilters.entries()).forEach(([key, value]) => {
                    if (value) {
                        const filterOption = this.extraFilterOptions.find((option) => option.label(guaranteeNonNullable(this.queryBuilderState)) ===
                            key);
                        if (filterOption) {
                            searchSpecification = filterOption.filterFunction(searchSpecification, guaranteeNonNullable(this.queryBuilderState));
                        }
                    }
                });
            }
            searchSpecification =
                this.decorateSearchSpecification?.(searchSpecification) ??
                    searchSpecification;
            this.queries = (yield this.graphManager.searchQueries(searchSpecification));
            if (!querySearchSortBy) {
                this.queries = this.queries.toSorted((a, b) => a.name.localeCompare(b.name));
            }
            this.searchQueriesState.pass();
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.notificationService.notifyError(error);
            this.searchQueriesState.fail();
        }
    }
    *renameQuery(queryId, name) {
        this.renameQueryState.inProgress();
        try {
            const query = (yield this.graphManager.renameQuery(queryId, name));
            this.onQueryRenamed?.(query);
            this.applicationStore.notificationService.notifySuccess('Renamed query successfully');
            this.renameQueryState.pass();
            this.searchQueries(this.searchText); // trigger a search to refresh the query list
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.notificationService.notifyError(error);
            this.renameQueryState.fail();
        }
    }
    *deleteQuery(queryId) {
        this.deleteQueryState.inProgress();
        try {
            yield this.graphManager.deleteQuery(queryId);
            this.onQueryDeleted?.(queryId);
            this.applicationStore.notificationService.notifySuccess('Deleted query successfully');
            this.deleteQueryState.pass();
            this.searchQueries(this.searchText); // trigger a search to refresh the query list
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.notificationService.notifyError(error);
            this.deleteQueryState.fail();
        }
    }
    *getPreviewQueryContent(queryId, template) {
        this.previewQueryState.inProgress();
        try {
            if (queryId) {
                const queryInfo = (yield this.graphManager.getQueryInfo(queryId));
                this.queryPreviewContent = queryInfo;
                this.queryPreviewContent.content =
                    (yield this.graphManager.prettyLambdaContent(queryInfo.content));
            }
            else if (template) {
                this.queryPreviewContent = {
                    name: template.queryName,
                    content: '',
                };
                this.queryPreviewContent.content =
                    (yield this.graphManager.lambdaToPureCode(template.queryContent, true));
            }
            this.previewQueryState.pass();
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.notificationService.notifyError(error);
            this.previewQueryState.fail();
        }
    }
}
//# sourceMappingURL=QueryLoaderState.js.map