/**
 * @fileoverview Pure helpers for the Data Explorer dashboard's AI-agent integration.
 *
 * These functions are intentionally free of Angular / component dependencies so they
 * can be unit-tested in isolation. The component ({@link DataExplorerDashboardComponent})
 * supplies a plain snapshot of its current state and these helpers shape it into the
 * key-value `AgentContext` object that flows to the async chat agent and the realtime
 * co-agent via `NavigationService.SetAgentContext`.
 */
import { DataExplorerViewMode } from './models/explorer-state.interface';
/** The two entity-browser modes the home screen supports (All Entities vs My Favorites). */
export declare const VALID_ENTITY_BROWSER_MODES: readonly ('all' | 'favorites')[];
/**
 * The "MJ: " schema prefix carried by newer core entities (e.g. "MJ: ML Models",
 * "MJ: AI Models"). The UI strips it when an entity has no explicit DisplayName,
 * and users almost always say the stripped form ("ML Models", "AI Models") rather
 * than the full registered Name. See {@link entityDisplayName} / {@link stripMJPrefix}.
 */
export declare const MJ_ENTITY_NAME_PREFIX = "MJ: ";
/**
 * Upper bound on how many currently-loaded record display values we publish in the
 * record-view context (VisibleRecordNames). Bounded so the streamed note stays small
 * even when a page holds hundreds of rows; a companion LoadedRecordCount reports the
 * true number loaded.
 */
export declare const AGENT_CONTEXT_RECORD_LIST_CAP = 25;
/**
 * Strip the leading "MJ: " schema prefix from an entity Name, if present.
 * Pure + deterministic. Returns the input unchanged when the prefix is absent.
 *
 * @param name - a (possibly prefixed) entity Name, e.g. "MJ: ML Models"
 * @returns the name without the "MJ: " prefix, e.g. "ML Models"
 */
export declare function stripMJPrefix(name: string): string;
/**
 * The display label the Data Explorer shows for an entity — the same value the entity
 * cards render via `EntityInfo.DisplayNameOrName`, except we additionally strip the
 * "MJ: " schema prefix when no explicit DisplayName is set. This is what the user reads
 * on screen and therefore what they say ("ML Models", not "MJ: ML Models").
 *
 * @param name - the entity's registered Name (may carry an "MJ: " prefix)
 * @param displayName - the entity's DisplayName, if any (takes precedence, used verbatim)
 * @returns the user-facing display label
 */
export declare function entityDisplayName(name: string, displayName?: string | null): string;
/**
 * A minimal name-bearing entity descriptor, supplied by the component so the pure
 * resolver can match agent input against what the user sees. Mirrors the salient
 * slice of `EntityInfo` ({@link entityDisplayName} reads the same two fields).
 */
export interface EntityNameCandidate {
    Name: string;
    DisplayName?: string | null;
}
/**
 * Resolve an agent-supplied entity reference to one of the available entities, matching
 * the way a user names things. The user says the DISPLAY name (what the card shows),
 * but the registered Name may carry an "MJ: " prefix — so we try, in order:
 *   1. exact registered Name (case-insensitive)
 *   2. display name (case-insensitive) — DisplayName, else the prefix-stripped Name
 *   3. display name ignoring the "MJ: " prefix (case-insensitive)
 *
 * Pure + deterministic over the supplied candidate list, so it's unit-testable in
 * isolation; the component passes its `EntityInfo[]` (structurally `EntityNameCandidate[]`).
 *
 * @param input - whatever the agent passed (typically the on-screen display name)
 * @param candidates - the entities available in this explorer
 * @returns the matched candidate, or null on a miss
 */
export declare function resolveEntityByName<T extends EntityNameCandidate>(input: string, candidates: readonly T[]): T | null;
/**
 * Upper bound on how many names we publish in a name-list context field
 * (AvailableViews, VisibleColumns, AvailableEntities). Keeping the streamed note
 * bounded avoids flooding the co-agent with hundreds of names; when the underlying
 * list is larger we surface a companion total-count field instead.
 */
export declare const AGENT_CONTEXT_NAME_LIST_CAP = 25;
/**
 * Upper bound on how many application-group summaries we publish. The home screen
 * groups entities by application (Actions, Admin, AI, Archiving, …); there are
 * on the order of ~20 of these so a small cap keeps the streamed note bounded
 * while still letting the co-agent see the full landscape.
 */
export declare const AGENT_CONTEXT_APP_GROUP_CAP = 25;
/**
 * A request to select a loaded record, as the agent expresses it: either by ordinal
 * {@link RecordSelectionRequest.position} ('first' | 'last' | a 1-based index) OR by
 * {@link RecordSelectionRequest.name} (a contains/case-insensitive match on the record's
 * display value). Exactly one is honored; `position` takes precedence when both are given.
 */
export interface RecordSelectionRequest {
    position?: 'first' | 'last' | number;
    name?: string;
}
/** Outcome of {@link resolveRecordSelection}: a 0-based index into the loaded records, or an error. */
export type RecordSelectionResult = {
    ok: true;
    index: number;
} | {
    ok: false;
    error: string;
};
/**
 * Resolve an agent record-selection request against the display values of the records
 * currently loaded in the grid. Pure + deterministic over the supplied `recordNames`
 * (the component derives those from its `loadedRecords` via the entity's name field, in
 * the same order). Returns a 0-based index the component maps back to the actual record.
 *
 * Resolution order:
 *   - `position` first when present: 'first' → 0, 'last' → last, a 1-based number → number-1.
 *   - otherwise `name`: an exact case-insensitive match wins; failing that, the first
 *     case-insensitive *contains* match.
 *
 * @param recordNames - display values of the loaded records, in grid order
 * @param request - the agent's selection request
 * @returns the resolved 0-based index, or a clear error message
 */
export declare function resolveRecordSelection(recordNames: readonly string[], request: RecordSelectionRequest): RecordSelectionResult;
/**
 * Type-guard / validator for a record-view mode string. Used to keep the
 * `SetViewMode` client tool tolerant of arbitrary agent input — only the four
 * known modes are accepted.
 *
 * @param mode - candidate mode string (may be anything the agent passes)
 * @returns true when `mode` is one of grid | cards | timeline | map
 */
export declare function isValidViewMode(mode: unknown): mode is DataExplorerViewMode;
/**
 * Type-guard / validator for an entity-browser mode string, backing the
 * `SetEntityBrowserMode` client tool.
 *
 * @param mode - candidate mode string (may be anything the agent passes)
 * @returns true when `mode` is one of 'all' | 'favorites'
 */
export declare function isValidEntityBrowserMode(mode: unknown): mode is 'all' | 'favorites';
/**
 * A summary of one application group shown on the home screen's entity browser.
 * `Name` is the application name (e.g. "AI", "Admin", "System & Other"); `EntityCount`
 * is how many entities are currently visible under it (after the active filter/mode);
 * `Expanded` reflects whether the group is currently expanded in the UI.
 */
export interface AppGroupSummary {
    Name: string;
    EntityCount: number;
    Expanded: boolean;
}
/**
 * The plain, component-supplied snapshot used to build the agent context.
 * Mirrors the salient slice of {@link DataExplorerState} plus a couple of
 * component-derived fields (selected entity name, debounced filter text,
 * record counts, the home-view entity-search fields, the application-group
 * landscape, and pagination state).
 */
export interface DataExplorerAgentContextInput {
    /** Name of the currently selected entity, or null at the home level. */
    SelectedEntityName: string | null;
    /** Active record-view mode (grid/cards/timeline/map). */
    ViewMode: DataExplorerViewMode;
    /**
     * The record-view modes the CURRENT entity actually supports (e.g. 'map' only
     * when the entity supports geocoding, 'timeline' only when it has date fields).
     * Lets the co-agent avoid requesting an unsupported view type. Empty at home level.
     */
    AvailableViewTypes: DataExplorerViewMode[];
    /** ID of the currently selected saved view, or null. */
    ActiveViewId: string | null;
    /**
     * Resolved display name for {@link ActiveViewId}, or null when no view is active
     * (or the id couldn't be resolved). Lets the co-agent refer to the view by name
     * rather than an opaque GUID.
     */
    ActiveViewName: string | null;
    /**
     * Names of the saved views available for the currently selected entity (the ones
     * the agent can open via the SelectView tool). The component supplies the full
     * list; this helper bounds it — see {@link AGENT_CONTEXT_NAME_LIST_CAP}.
     */
    AvailableViewNames: string[];
    /**
     * Field/column names visible in the current entity's grid. The component supplies
     * the full list; this helper bounds it.
     */
    VisibleColumnNames: string[];
    /** The debounced record filter text currently applied to the grid. */
    FilterText: string;
    /** Total record count for the selected entity/view (unfiltered). */
    TotalRecordCount: number;
    /** Record count after the current filter is applied. */
    FilteredRecordCount: number;
    /**
     * Number of records loaded per page in the grid (server-side pagination page size).
     * Used to derive {@link TotalPages} when the live grid hasn't reported a page count.
     */
    PageSize: number;
    /**
     * Live 1-based current page reported by the inner grid, or null when the grid
     * hasn't mounted / reported yet (e.g. before first data load).
     */
    CurrentPage: number | null;
    /**
     * Live total page count reported by the inner grid, or null when unavailable.
     * When present it takes precedence over the count derived from record counts.
     */
    TotalPages: number | null;
    /**
     * Field/column the grid is currently sorted by, or null when unsorted.
     */
    SortColumn: string | null;
    /**
     * Active sort direction ('asc' | 'desc'), or null when unsorted.
     */
    SortDirection: 'asc' | 'desc' | null;
    /**
     * Names of the entities related to the selected entity (from EntityInfo.RelatedEntities
     * metadata), so the agent can suggest NavigateToRelated targets. The component supplies
     * the full list; this helper bounds it — see {@link AGENT_CONTEXT_NAME_LIST_CAP}.
     * Empty at the home level.
     */
    RelatedEntityNames: string[];
    /** Display name of the currently selected record, or null. */
    SelectedRecordName: string | null;
    /** Whether the detail panel is currently open. */
    DetailPanelOpen: boolean;
    /**
     * Display values of the records currently loaded in the grid, in grid order — so the
     * agent knows what's selectable (and can pick "the first one" or one by name via the
     * SelectRecord tool). The component supplies the full loaded set; this helper bounds it —
     * see {@link AGENT_CONTEXT_RECORD_LIST_CAP}. Empty at the home level / before first load.
     */
    VisibleRecordNames: string[];
    /** Total number of records loaded in the current page of the grid (may exceed VisibleRecordNames after the cap). */
    LoadedRecordCount: number;
    /** Home-view mode (all vs favorites) — only meaningful at the home level. */
    HomeViewMode: 'all' | 'favorites';
    /** The entity-search text on the home screen. */
    EntitySearchText: string;
    /** Count of entities currently visible after the home-screen filter. */
    VisibleEntityCount: number;
    /** Count of entities the current user has favorited (across all applications). */
    FavoriteEntityCount: number;
    /**
     * Names of the entities loaded and available at the home level (so the co-agent
     * can navigate to one via OpenEntityData). The component supplies the full list;
     * this helper bounds it — see {@link AGENT_CONTEXT_NAME_LIST_CAP}.
     */
    AvailableEntityNames: string[];
    /**
     * Application-group summaries currently shown on the home screen's entity browser.
     * Empty when the explorer is scoped to a single application (no grouping). The
     * component supplies the full list; this helper bounds it — see
     * {@link AGENT_CONTEXT_APP_GROUP_CAP}.
     */
    AppGroups: AppGroupSummary[];
}
/**
 * Derive the total page count from a record count and page size.
 * Guards against a non-positive page size (returns 1 page) and rounds up.
 */
export declare function computeTotalPages(recordCount: number, pageSize: number): number;
/**
 * Build the agent-visible context object for the Data Explorer.
 *
 * When an entity is selected the context describes the record-browsing surface
 * (entity, view mode, available view types, active saved view, filter, record
 * counts, pagination, selected record, detail-panel state). When no entity is
 * selected (home level) it instead describes the entity-browsing surface
 * (home/browser view mode, entity search text, count of visible entities,
 * favorite count, available entities, and the application-group landscape) and
 * reports `AtHomeLevel: true`.
 *
 * Keeping this a pure function (no `this`) makes the context shape unit-testable
 * and decouples it from change-detection timing.
 *
 * @param input - the component's current state snapshot
 * @returns a flat key-value object suitable for `SetAgentContext`
 */
export declare function buildDataExplorerAgentContext(input: DataExplorerAgentContextInput): Record<string, unknown>;
//# sourceMappingURL=data-explorer-agent-context.d.ts.map