/**
 * 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 { ActionState, LogEvent, assertErrorThrown, guaranteeNonNullable, isNonNullable, } from '@finos/legend-shared';
import { action, computed, flow, makeObservable, observable } from 'mobx';
import { LEGEND_STUDIO_APP_EVENT } from '../__lib__/LegendStudioEvent.js';
import { ShowcaseRegistryServerClient, } from '@finos/legend-server-showcase';
import { ApplicationExtensionState, DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH, } from '@finos/legend-application';
import { DIRECTORY_PATH_DELIMITER } from '@finos/legend-graph';
import { SHOWCASE_MANAGER_VIRTUAL_ASSISTANT_TAB_KEY } from '../components/extensions/Core_LegendStudioApplicationPlugin.js';
import { LegendStudioTelemetryHelper } from '../__lib__/LegendStudioTelemetryHelper.js';
export var SHOWCASE_MANAGER_VIEW;
(function (SHOWCASE_MANAGER_VIEW) {
    SHOWCASE_MANAGER_VIEW["EXPLORER"] = "EXPLORER";
    SHOWCASE_MANAGER_VIEW["SEARCH"] = "SEARCH";
})(SHOWCASE_MANAGER_VIEW || (SHOWCASE_MANAGER_VIEW = {}));
export var SHOWCASE_MANAGER_SEARCH_CATEGORY;
(function (SHOWCASE_MANAGER_SEARCH_CATEGORY) {
    SHOWCASE_MANAGER_SEARCH_CATEGORY["SHOWCASE"] = "SHOWCASE";
    SHOWCASE_MANAGER_SEARCH_CATEGORY["CODE"] = "CODE";
})(SHOWCASE_MANAGER_SEARCH_CATEGORY || (SHOWCASE_MANAGER_SEARCH_CATEGORY = {}));
export class ShowcasesExplorerTreeNodeData {
    isOpen;
    id;
    label;
    parentId;
    childrenIds = [];
    metadata;
    constructor(id, label, parentId, metadata) {
        this.id = id;
        this.label = label;
        this.parentId = parentId;
        this.metadata = metadata;
    }
}
const buildShowcasesExplorerTreeNode = (showcase, path, parentId, nodes, rootIds) => {
    let node;
    const idx = path.indexOf(DIRECTORY_PATH_DELIMITER);
    if (idx === -1) {
        // showcase node
        node = new ShowcasesExplorerTreeNodeData(`${parentId ? `${parentId}${DIRECTORY_PATH_DELIMITER}` : ''}${path}`, showcase.title, parentId, showcase);
    }
    else {
        // directory node
        const directoryName = path.substring(0, idx);
        const directoryNodeId = `${parentId ? `${parentId}${DIRECTORY_PATH_DELIMITER}` : ''}${directoryName}`;
        node =
            nodes.get(directoryNodeId) ??
                new ShowcasesExplorerTreeNodeData(directoryNodeId, directoryName, undefined, undefined);
    }
    nodes.set(node.id, node);
    if (!parentId && !rootIds.includes(node.id)) {
        rootIds.push(node.id);
    }
    if (parentId) {
        const parentNode = nodes.get(parentId);
        if (parentNode) {
            if (!parentNode.childrenIds.includes(node.id)) {
                parentNode.childrenIds.push(node.id);
            }
        }
    }
    if (idx !== -1) {
        buildShowcasesExplorerTreeNode(showcase, path.substring(idx + 1), node.id, nodes, rootIds);
    }
    return node;
};
const buildShowcasesExplorerTreeData = (showcases) => {
    const rootIds = [];
    const nodes = new Map();
    showcases.forEach((showcase) => buildShowcasesExplorerTreeNode(showcase, showcase.path, undefined, nodes, rootIds));
    return { rootIds, nodes };
};
export class ShowcaseManagerState extends ApplicationExtensionState {
    static IDENTIFIER = 'showcase-manager';
    applicationStore;
    initState = ActionState.create();
    fetchShowcaseState = ActionState.create();
    textSearchState = ActionState.create();
    showcaseServerClient;
    allShowcases;
    currentShowcase;
    showcaseLineToScroll;
    currentView = SHOWCASE_MANAGER_VIEW.EXPLORER;
    explorerTreeData;
    searchText = '';
    showcaseSearchResults;
    textSearchResults;
    currentSearchCaterogy = SHOWCASE_MANAGER_SEARCH_CATEGORY.SHOWCASE;
    constructor(applicationStore) {
        super();
        makeObservable(this, {
            allShowcases: observable,
            currentShowcase: observable,
            currentView: observable,
            explorerTreeData: observable.ref,
            searchText: observable,
            textSearchResults: observable.ref,
            showcaseSearchResults: observable.ref,
            currentSearchCaterogy: observable,
            showcaseLineToScroll: observable,
            nonDevShowcases: computed,
            logOpenManager: action,
            setCurrentView: action,
            closeShowcase: action,
            setExplorerTreeData: action,
            setSearchText: action,
            resetSearch: action,
            setCurrentSearchCategory: action,
            search: flow,
            initialize: flow,
            openShowcase: flow,
        });
        this.applicationStore = applicationStore;
        if (this.applicationStore.config.showcaseServerUrl) {
            this.showcaseServerClient = new ShowcaseRegistryServerClient({
                baseUrl: this.applicationStore.config.showcaseServerUrl,
            });
        }
    }
    get INTERNAL__identifierKey() {
        return ShowcaseManagerState.IDENTIFIER;
    }
    get nonDevShowcases() {
        return this.allShowcases?.filter((showcase) => !showcase.development) ?? [];
    }
    static retrieveNullableState(applicationStore) {
        return applicationStore.extensionStates.find((extensionState) => {
            if (
            /**
             * In development mode, when we make changes in certain areas like utils or base states, the following `instanceof`
             * check will fail as if there were multiple copies of the classes with the same name, this could be caused by either
             * React `fast-refresh` or `webpack HMR`; we didn't have time to really do a thorough debug here, as such,
             * we will just do a simple key check to match the right state to bypass the problem for development mode.
             */
            // eslint-disable-next-line no-process-env
            process.env.NODE_ENV === 'development') {
                return (extensionState.INTERNAL__identifierKey ===
                    ShowcaseManagerState.IDENTIFIER);
            }
            return extensionState instanceof ShowcaseManagerState;
        });
    }
    static retrieveState(applicationStore) {
        return guaranteeNonNullable(ShowcaseManagerState.retrieveNullableState(applicationStore), `Can't find showcase manager state: make sure it is added as an editor extension state`);
    }
    get isEnabled() {
        return Boolean(this.showcaseServerClient);
    }
    get client() {
        return guaranteeNonNullable(this.showcaseServerClient, `Showcase registry server client is not configured`);
    }
    setCurrentView(val) {
        this.currentView = val;
    }
    *openShowcase(metadata, showcaseLineToScroll) {
        this.fetchShowcaseState.inProgress();
        try {
            const showcase = (yield this.client.getShowcase(metadata.path));
            this.currentShowcase = showcase;
            LegendStudioTelemetryHelper.logEvent_ShowcaseManagerShowcaseProjectLaunch(this.applicationStore.telemetryService, {
                showcasePath: showcase.path,
            });
            this.showcaseLineToScroll = showcaseLineToScroll;
            this.fetchShowcaseState.pass();
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SHOWCASE_MANAGER_FAILURE), error);
            this.fetchShowcaseState.fail();
        }
    }
    logOpenManager() {
        if (this.allShowcases) {
            const report = {
                showcasesTotalCount: this.allShowcases.length,
                showcasesDevelopmentCount: this.nonDevShowcases.length,
            };
            LegendStudioTelemetryHelper.logEvent_ShowcaseManagerLaunch(this.applicationStore.telemetryService, report);
        }
    }
    closeShowcase() {
        this.currentShowcase = undefined;
        this.showcaseLineToScroll = undefined;
    }
    setExplorerTreeData(val) {
        this.explorerTreeData = val;
    }
    setSearchText(val) {
        this.searchText = val;
    }
    resetSearch() {
        this.searchText = '';
        this.textSearchResults = undefined;
        this.showcaseSearchResults = undefined;
    }
    setCurrentSearchCategory(val) {
        this.currentSearchCaterogy = val;
    }
    *initialize() {
        if (!this.isEnabled || this.initState.isInProgress) {
            return;
        }
        this.initState.inProgress();
        try {
            this.allShowcases =
                (yield this.client.getShowcases());
            this.explorerTreeData = buildShowcasesExplorerTreeData(this.nonDevShowcases);
            // expand all the root nodes by default
            this.explorerTreeData.rootIds.forEach((rootId) => {
                const rootNode = this.explorerTreeData?.nodes.get(rootId);
                if (rootNode) {
                    rootNode.isOpen = true;
                }
            });
            this.setExplorerTreeData({ ...this.explorerTreeData });
            this.initState.pass();
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SHOWCASE_MANAGER_FAILURE), error);
            this.initState.fail();
        }
    }
    *search() {
        if (this.textSearchState.isInProgress ||
            this.searchText.length <= DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH) {
            return;
        }
        this.textSearchState.inProgress();
        try {
            const result = (yield this.client.search(this.searchText));
            this.textSearchResults = result.textMatches
                .map((match) => {
                const matchingShowcase = this.nonDevShowcases.find((showcase) => showcase.path === match.path);
                if (matchingShowcase) {
                    return {
                        showcase: matchingShowcase,
                        match,
                    };
                }
                return undefined;
            })
                .filter(isNonNullable);
            this.showcaseSearchResults = result.showcases
                .map((showcasePath) => this.nonDevShowcases.find((showcase) => showcase.path === showcasePath))
                .filter(isNonNullable);
        }
        catch (error) {
            assertErrorThrown(error);
            this.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.SHOWCASE_MANAGER_FAILURE), error);
        }
        finally {
            this.textSearchState.complete();
        }
    }
}
export const openShowcaseManager = (applicationStore) => {
    const showcaseManagerState = ShowcaseManagerState.retrieveNullableState(applicationStore);
    if (showcaseManagerState?.isEnabled) {
        applicationStore.assistantService.setIsHidden(false);
        applicationStore.assistantService.setIsOpen(true);
        applicationStore.assistantService.setIsPanelMaximized(true);
        applicationStore.assistantService.setSelectedTab(SHOWCASE_MANAGER_VIRTUAL_ASSISTANT_TAB_KEY);
        showcaseManagerState.logOpenManager();
    }
};
//# sourceMappingURL=ShowcaseManagerState.js.map