import { SerializationFactory, returnUndefOnError, usingModelSchema, } from '@finos/legend-shared';
import { WorkspaceType } from '@finos/legend-server-sdlc';
import { createModelSchema, list, optional, primitive } from 'serializr';
/**
 * 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.
 */
export var LEGEND_STUDIO_USER_DATA_KEY;
(function (LEGEND_STUDIO_USER_DATA_KEY) {
    LEGEND_STUDIO_USER_DATA_KEY["GLOBAL_TEST_RUNNER_SHOW_DEPENDENCIES"] = "studio-editor.global-test-runner-showDependencyPanel";
    // Per-user theme preference for the database editor. Scoped to this one
    // editor since the wider Studio app is dark-mode-only today — the rest of
    // the app does not honor this value.
    // TODO: when Studio adopts app-wide theming via `LayoutService` (the
    // mechanism Query already uses with setting key
    // `application.layout.colorTheme`), retire this key and have the database
    // editor inherit `applicationStore.layoutService.currentColorTheme`
    // instead. Migration is mechanical: delete this key + the helper getters,
    // drop the toggle button in the tab header, and retarget the SCSS
    // `.database-editor--light` block at the framework's color-theme tokens.
    LEGEND_STUDIO_USER_DATA_KEY["DATABASE_EDITOR_THEME"] = "studio-editor.database-editor.theme";
    // Recently-opened projects and (non-patch) workspaces shown on the
    // workspace setup screen to speed up re-opening common work.
    LEGEND_STUDIO_USER_DATA_KEY["WORKSPACE_SETUP_RECENTS"] = "studio-editor.workspace-setup.recents";
    // Per-user cache of the sandbox-access boolean + the sandbox project id,
    // so the workspace setup screen can render the sandbox UI without waiting
    // on the `userHasPrototypeProjectAccess` graph manager call AND a
    // sandbox-tag project search on every mount. Revalidated against SDLC in
    // the background; invalidated automatically on 404 or after the TTL.
    LEGEND_STUDIO_USER_DATA_KEY["WORKSPACE_SETUP_SANDBOX_INFO"] = "studio-editor.workspace-setup.sandboxInfo";
})(LEGEND_STUDIO_USER_DATA_KEY || (LEGEND_STUDIO_USER_DATA_KEY = {}));
// --- Workspace setup recents -------------------------------------------------
const WORKSPACE_SETUP_RECENTS_VERSION = 1;
const MAX_RECENT_PROJECTS = 10;
const MAX_RECENT_WORKSPACES = 20;
export class RecentProjectEntry {
    projectId;
    name;
    description;
    webUrl;
    tags;
    lastOpenedAt;
    static serialization = new SerializationFactory(createModelSchema(RecentProjectEntry, {
        description: primitive(),
        lastOpenedAt: primitive(),
        name: primitive(),
        projectId: primitive(),
        tags: list(primitive()),
        webUrl: primitive(),
    }));
}
export class RecentWorkspaceEntry {
    projectId;
    workspaceId;
    workspaceType;
    lastOpenedAt;
    static serialization = new SerializationFactory(createModelSchema(RecentWorkspaceEntry, {
        lastOpenedAt: primitive(),
        projectId: primitive(),
        workspaceId: primitive(),
        // WorkspaceType is a string enum; stored/loaded as a plain string and
        // validated when the entry is consumed.
        workspaceType: primitive(),
    }));
}
export class WorkspaceSetupRecents {
    version = WORKSPACE_SETUP_RECENTS_VERSION;
    projects = [];
    workspaces = [];
    static serialization = new SerializationFactory(createModelSchema(WorkspaceSetupRecents, {
        projects: list(usingModelSchema(RecentProjectEntry.serialization.schema)),
        version: primitive(),
        workspaces: list(usingModelSchema(RecentWorkspaceEntry.serialization.schema)),
    }));
}
const isValidWorkspaceType = (v) => v === WorkspaceType.USER || v === WorkspaceType.GROUP;
const emptyRecents = () => new WorkspaceSetupRecents();
const readRecents = (service) => {
    const raw = returnUndefOnError(() => service.getObjectValue(LEGEND_STUDIO_USER_DATA_KEY.WORKSPACE_SETUP_RECENTS));
    if (!raw) {
        return emptyRecents();
    }
    const parsed = returnUndefOnError(() => WorkspaceSetupRecents.serialization.fromJson(raw));
    if (!parsed) {
        return emptyRecents();
    }
    // Defensive post-checks: drop entries with invalid enum values and enforce
    // the LRU caps in case the persisted blob was tampered with.
    parsed.workspaces = parsed.workspaces
        .filter((w) => isValidWorkspaceType(w.workspaceType))
        .slice(0, MAX_RECENT_WORKSPACES);
    parsed.projects = parsed.projects.slice(0, MAX_RECENT_PROJECTS);
    return parsed;
};
const writeRecents = (service, recents) => {
    service.persistValue(LEGEND_STUDIO_USER_DATA_KEY.WORKSPACE_SETUP_RECENTS, WorkspaceSetupRecents.serialization.toJson(recents));
};
// --- Cached sandbox info -----------------------------------------------------
// Sandbox access and the sandbox project id rarely change for a given user,
// but they're costly to look up on every setup mount (one graph manager call
// + one tagged-project search). Cache the result for a day and revalidate
// in the background on the fast path.
const SANDBOX_INFO_TTL_MS = 24 * 60 * 60 * 1000;
export class CachedSandboxInfo {
    userId;
    hasAccess;
    /** undefined when the user has access but hasn't created a sandbox yet. */
    projectId;
    fetchedAt;
    static serialization = new SerializationFactory(createModelSchema(CachedSandboxInfo, {
        fetchedAt: primitive(),
        hasAccess: primitive(),
        projectId: optional(primitive()),
        userId: primitive(),
    }));
}
export class LegendStudioUserDataHelper {
    static globalTestRunner_getShowDependencyPanel(service) {
        return returnUndefOnError(() => service.getBooleanValue(LEGEND_STUDIO_USER_DATA_KEY.GLOBAL_TEST_RUNNER_SHOW_DEPENDENCIES));
    }
    static globalTestRunner_setShowDependencyPanel(service, val) {
        service.persistValue(LEGEND_STUDIO_USER_DATA_KEY.GLOBAL_TEST_RUNNER_SHOW_DEPENDENCIES, val);
    }
    static databaseEditor_getTheme(service) {
        const val = returnUndefOnError(() => service.getStringValue(LEGEND_STUDIO_USER_DATA_KEY.DATABASE_EDITOR_THEME));
        return val === 'light' || val === 'dark' ? val : undefined;
    }
    static databaseEditor_setTheme(service, val) {
        service.persistValue(LEGEND_STUDIO_USER_DATA_KEY.DATABASE_EDITOR_THEME, val);
    }
    // --- Workspace setup recents ---------------------------------------------
    static workspaceSetup_getRecentProjects(service) {
        return readRecents(service).projects;
    }
    static workspaceSetup_getRecentWorkspaces(service) {
        return readRecents(service).workspaces;
    }
    static workspaceSetup_recordRecentProject(service, entry) {
        const recents = readRecents(service);
        const next = new RecentProjectEntry();
        next.projectId = entry.projectId;
        next.name = entry.name;
        next.description = entry.description;
        next.webUrl = entry.webUrl;
        next.tags = entry.tags;
        next.lastOpenedAt = Date.now();
        recents.projects = [
            next,
            ...recents.projects.filter((p) => p.projectId !== entry.projectId),
        ].slice(0, MAX_RECENT_PROJECTS);
        writeRecents(service, recents);
        return recents.projects;
    }
    static workspaceSetup_recordRecentWorkspace(service, entry) {
        const recents = readRecents(service);
        const next = new RecentWorkspaceEntry();
        next.projectId = entry.projectId;
        next.workspaceId = entry.workspaceId;
        next.workspaceType = entry.workspaceType;
        next.lastOpenedAt = Date.now();
        recents.workspaces = [
            next,
            ...recents.workspaces.filter((w) => !(w.projectId === entry.projectId &&
                w.workspaceId === entry.workspaceId &&
                w.workspaceType === entry.workspaceType)),
        ].slice(0, MAX_RECENT_WORKSPACES);
        writeRecents(service, recents);
        return recents.workspaces;
    }
    static workspaceSetup_removeRecentProject(service, projectId) {
        const recents = readRecents(service);
        recents.projects = recents.projects.filter((p) => p.projectId !== projectId);
        recents.workspaces = recents.workspaces.filter((w) => w.projectId !== projectId);
        writeRecents(service, recents);
        return recents;
    }
    static workspaceSetup_removeRecentWorkspace(service, entry) {
        const recents = readRecents(service);
        recents.workspaces = recents.workspaces.filter((w) => !(w.projectId === entry.projectId &&
            w.workspaceId === entry.workspaceId &&
            w.workspaceType === entry.workspaceType));
        writeRecents(service, recents);
        return recents.workspaces;
    }
    static workspaceSetup_clearRecents(service) {
        writeRecents(service, emptyRecents());
    }
    // --- Cached sandbox info -------------------------------------------------
    static workspaceSetup_getCachedSandboxInfo(service, currentUserId) {
        const raw = returnUndefOnError(() => service.getObjectValue(LEGEND_STUDIO_USER_DATA_KEY.WORKSPACE_SETUP_SANDBOX_INFO));
        if (!raw) {
            return undefined;
        }
        const parsed = returnUndefOnError(() => CachedSandboxInfo.serialization.fromJson(raw));
        if (!parsed) {
            return undefined;
        }
        // Discard entries that don't belong to the user looking at the screen
        // (e.g., after a user switch on a shared machine) or that have aged out.
        if (parsed.userId !== currentUserId) {
            return undefined;
        }
        if (Date.now() - parsed.fetchedAt > SANDBOX_INFO_TTL_MS) {
            return undefined;
        }
        return parsed;
    }
    static workspaceSetup_recordSandboxInfo(service, info) {
        const entry = new CachedSandboxInfo();
        entry.userId = info.userId;
        entry.hasAccess = info.hasAccess;
        entry.projectId = info.projectId;
        entry.fetchedAt = Date.now();
        service.persistValue(LEGEND_STUDIO_USER_DATA_KEY.WORKSPACE_SETUP_SANDBOX_INFO, CachedSandboxInfo.serialization.toJson(entry));
    }
    static workspaceSetup_clearSandboxInfo(service) {
        service.persistValue(LEGEND_STUDIO_USER_DATA_KEY.WORKSPACE_SETUP_SANDBOX_INFO, undefined);
    }
}
//# sourceMappingURL=LegendStudioUserDataHelper.js.map