import { ApplicationInfo, BaseEngine, IMetadataProvider, UserInfo } from '@memberjunction/core';
import { Observable } from 'rxjs';
/**
 * Status indicating why a user can or cannot access an application.
 * - 'installed_active': User has UserApplication record with IsActive=true
 * - 'installed_inactive': User has UserApplication record with IsActive=false
 * - 'not_installed': User has no UserApplication record for this app
 * - 'not_authorized': User's roles do not grant access to the application
 */
export type UserApplicationAccessStatus = 'installed_active' | 'installed_inactive' | 'not_installed' | 'not_authorized';
/**
 * Optional filter that consuming projects can register to customize
 * application access checks. Called by `UserHasApplicationAccess()` after
 * the default global role check. The filter receives the result of the
 * default check and can override it.
 *
 * @param applicationId - The application being checked
 * @param defaultAccess - The result of the default global role check
 * @param user - The current UserInfo (includes TenantContext if set by middleware)
 * @returns Whether the user should have access to the application
 */
export type ApplicationAccessFilter = (applicationId: string, defaultAccess: boolean, user: UserInfo) => boolean;
/**
 * Optional filter that consuming projects can register to customize
 * application admin checks. Called by `UserCanAdminApplication()` after
 * the default global role check.
 *
 * @param applicationId - The application being checked
 * @param defaultCanAdmin - The result of the default global role check
 * @param user - The current UserInfo (includes TenantContext if set by middleware)
 * @returns Whether the user should have admin access to the application
 */
export type ApplicationAdminFilter = (applicationId: string, defaultCanAdmin: boolean, user: UserInfo) => boolean;
import { MJApplicationRoleEntity, MJUserNotificationEntity, MJUserNotificationTypeEntity, MJWorkspaceEntity, MJUserApplicationEntity, MJUserFavoriteEntity, MJUserRecordLogEntity, MJUserSettingEntity, MJUserNotificationPreferenceEntity } from '../generated/entity_subclasses.js';
/**
 * UserInfoEngine is a singleton engine that provides centralized access to user-specific data
 * including notifications, workspaces, applications, favorites, and record logs.
 *
 * This engine consolidates multiple user-related RunView calls into a single batched load,
 * improving performance and enabling local caching for faster subsequent access.
 *
 * Usage:
 * ```typescript
 * // Get the instance (auto-configured on startup)
 * const engine = UserInfoEngine.Instance;
 *
 * // Access user data
 * const notifications = engine.UserNotifications;
 * const workspace = engine.CurrentWorkspace;
 * const apps = engine.UserApplications;
 * ```
 *
 * Note: This engine filters all data by the current user's ID automatically.
 * On the server side, you must call Config() with contextUser to specify which user's data to load.
 */
export declare class UserInfoEngine extends BaseEngine<UserInfoEngine> {
    /**
     * Returns the global instance of the class. This is a singleton class, so there is only one instance of it in the application.
     * Do not directly create new instances of it, always use this method to get the instance.
     */
    static get Instance(): UserInfoEngine;
    private _UserNotifications;
    private _Workspaces;
    private _UserApplications;
    private _UserFavorites;
    private _UserRecordLogs;
    private _UserSettings;
    private _NotificationTypes;
    private _UserNotificationPreferences;
    private _applicationRoles;
    private _applicationAccessFilter;
    private _applicationAdminFilter;
    private _loadedForUserId;
    private _createDefaultAppsPromise;
    /**
     * Debounce time in milliseconds for SetSettingDebounced calls.
     * Default is 500ms. Change via the SettingsDebounceMs setter.
     */
    private _settingsDebounceMs;
    /**
     * Map of pending setting updates: key -> { value, contextUser, timestamp }
     * These are queued and flushed after the debounce period of inactivity.
     */
    private _pendingSettings;
    /**
     * Timer handle for the debounce flush
     */
    private _settingsDebounceTimer;
    /**
     * Promise that resolves when the current flush operation completes.
     * Used to prevent concurrent flush operations.
     */
    private _flushPromise;
    /**
     * Configures the engine by loading user-specific metadata from the database.
     * All entities are filtered by the current user's ID and cached locally for performance.
     *
     * @param forceRefresh - If true, forces a refresh from the server even if data is cached
     * @param contextUser - The user context (required for server-side, auto-detected on client)
     * @param provider - Optional custom metadata provider
     */
    Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>;
    /**
     * Observable stream of the notifications cache array. Emits the current array on subscribe
     * and re-emits whenever the cache is mutated (save, delete, remote-invalidate, refresh).
     *
     * Emits the raw unfiltered cache (all users). Consumers that need per-user filtering should
     * `pipe(map(...))` — the public {@link UserNotifications} getter applies the current-user filter.
     */
    get UserNotifications$(): Observable<MJUserNotificationEntity[]>;
    /**
     * Observable stream of the user favorites cache array. Emits the current array on subscribe
     * and re-emits whenever the cache is mutated.
     */
    get UserFavorites$(): Observable<MJUserFavoriteEntity[]>;
    /**
     * Observable stream of the user applications cache array. Emits the current array on subscribe
     * and re-emits whenever the cache is mutated.
     */
    get UserApplications$(): Observable<MJUserApplicationEntity[]>;
    /**
     * Get all notifications for the current user, ordered by creation date (newest first)
     */
    get UserNotifications(): MJUserNotificationEntity[];
    /**
     * Get all settings for the current user
     */
    get UserSettings(): MJUserSettingEntity[];
    /**
     * Get a user setting value by key.
     *
     * **Read-after-write semantics**: this consults the in-memory pending-
     * debounced-writes map FIRST. Without that, a `SetSettingDebounced`
     * followed immediately by `GetSetting` would return the old DB-cached
     * value because the debounce timer hasn't fired yet and the entity
     * hasn't been saved. Callers that update a preference and re-render
     * synchronously (e.g. form-variant picker → form reload) depend on
     * this freshness guarantee.
     *
     * @param settingKey - The setting key to find (e.g., "default-view-setting/Contacts")
     * @returns The setting value string, or undefined if not found
     */
    GetSetting(settingKey: string): string | undefined;
    /**
     * Get a user setting entity by key.
     * @param settingKey - The setting key to find
     * @returns The MJUserSettingEntity, or undefined if not found
     */
    GetSettingEntity(settingKey: string): MJUserSettingEntity | undefined;
    /**
     * Set a user setting by key. Creates a new setting if it doesn't exist.
     * @param settingKey - The setting key (e.g., "default-view-setting/Contacts")
     * @param value - The setting value (string, typically JSON for complex data)
     * @param contextUser - Optional user context for server-side use
     * @returns true if successful, false otherwise
     */
    SetSetting(settingKey: string, value: string, contextUser?: UserInfo): Promise<boolean>;
    /**
     * Delete a user setting by key.
     * @param settingKey - The setting key to delete
     * @returns true if successful (or setting didn't exist), false on error
     */
    DeleteSetting(settingKey: string): Promise<boolean>;
    /**
     * Get the current debounce time in milliseconds for SetSettingDebounced calls.
     */
    get SettingsDebounceMs(): number;
    /**
     * Set the debounce time in milliseconds for SetSettingDebounced calls.
     * When changed, any pending settings are flushed first before the new debounce time takes effect.
     * @param value - The debounce time in milliseconds (minimum 100ms, maximum 10000ms)
     */
    set SettingsDebounceMs(value: number);
    /**
     * Queue a setting update with debouncing. Multiple calls within the debounce period
     * are batched together, with only the last value for each key being saved.
     * The actual database save occurs after the debounce period of inactivity.
     *
     * This is the preferred method for UI components that may update settings frequently
     * (e.g., on every resize, scroll, or input change).
     *
     * @param settingKey - The setting key (e.g., "AI_DASHBOARD_ROOT/ai-models")
     * @param value - The setting value (string, typically JSON for complex data)
     * @param contextUser - Optional user context for server-side use
     */
    SetSettingDebounced(settingKey: string, value: string, contextUser?: UserInfo): void;
    /**
     * Immediately flush all pending debounced settings to the database.
     * Call this when you need to ensure settings are saved (e.g., before navigation).
     * Safe to call multiple times - concurrent calls will wait for the current flush to complete.
     *
     * @returns Promise that resolves when all pending settings have been saved
     */
    FlushPendingSettings(): Promise<void>;
    /**
     * Internal method to perform the actual flush of settings.
     * @param settingsToSave - Map of settings to save
     */
    private doFlushSettings;
    /**
     * Check if there are any pending debounced settings waiting to be saved.
     */
    get HasPendingSettings(): boolean;
    /**
     * Get the number of pending debounced settings.
     */
    get PendingSettingsCount(): number;
    /**
     * Get unread notifications for the current user
     */
    get UnreadNotifications(): MJUserNotificationEntity[];
    /**
     * Get the count of unread notifications
     */
    get UnreadNotificationCount(): number;
    /**
     * Get all workspaces for the current user
     */
    get Workspaces(): MJWorkspaceEntity[];
    /**
     * Get the current user's primary workspace (first one if multiple exist)
     */
    get CurrentWorkspace(): MJWorkspaceEntity | null;
    /**
     * Get all applications enabled for the current user, ordered by sequence then application name
     */
    get UserApplications(): MJUserApplicationEntity[];
    /**
     * Get all favorites for the current user, ordered by creation date (newest first)
     */
    get UserFavorites(): MJUserFavoriteEntity[];
    /**
     * Get all record logs for the current user (recent record access), ordered by LatestAt (most recent first)
     */
    get UserRecordLogs(): MJUserRecordLogEntity[];
    /**
     * Get ALL notifications in the cache (unfiltered by user).
     * Useful for server-side admin scenarios.
     */
    get AllNotifications(): MJUserNotificationEntity[];
    /**
     * Get ALL user applications in the cache (unfiltered by user).
     * Useful for server-side admin scenarios.
     */
    get AllUserApplications(): MJUserApplicationEntity[];
    /**
     * Get notifications for a specific user
     * @param userId - The user ID to filter by
     */
    GetNotificationsForUser(userId: string): MJUserNotificationEntity[];
    /**
     * Get user applications for a specific user
     * @param userId - The user ID to filter by
     */
    GetUserApplicationsForUser(userId: string): MJUserApplicationEntity[];
    /**
     * Get a notification by ID
     * @param notificationId - The notification ID to find
     */
    GetNotificationById(notificationId: string): MJUserNotificationEntity | undefined;
    /**
     * Get a user application by application ID
     * @param applicationId - The application ID to find
     */
    GetUserApplicationByAppId(applicationId: string): MJUserApplicationEntity | undefined;
    /**
     * Get favorites for a specific entity
     * @param entityId - The entity ID to filter by
     */
    GetFavoritesForEntity(entityId: string): MJUserFavoriteEntity[];
    /**
     * Get recent record logs for a specific entity
     * @param entityId - The entity ID to filter by
     * @param maxItems - Maximum number of items to return (default: 10)
     */
    GetRecentRecordsForEntity(entityId: string, maxItems?: number): MJUserRecordLogEntity[];
    /**
     * Check if a record is in the user's favorites
     * @param entityId - The entity ID
     * @param recordId - The record ID
     */
    IsRecordFavorite(entityId: string, recordId: string): boolean;
    /**
     * Get the user ID this engine was loaded for
     */
    get LoadedForUserId(): string | null;
    /**
     * Check the user's access status for an application.
     * First checks role-based authorization (ApplicationRole records), then installation status.
     * @param applicationId - The application ID to check
     * @returns The user's access status for this application
     */
    CheckUserApplicationAccess(applicationId: string): UserApplicationAccessStatus;
    /**
     * Read-only view of the ApplicationRole catalog. Used by permission providers
     * that need to reason about grants for arbitrary users (not just CurrentUser).
     */
    get ApplicationRoles(): readonly MJApplicationRoleEntity[];
    /**
     * Register a custom filter for application access checks. The filter is
     * called by `UserHasApplicationAccess()` after the default global role check.
     * It receives the default result and can override it based on custom logic
     * (e.g., tenant-scoped roles, feature flags, license restrictions).
     *
     * Only one filter can be registered at a time. Calling this again replaces
     * the previous filter. Pass `null` to remove the filter.
     *
     * @example
     * ```typescript
     * // Multi-tenant: scope access to the current tenant's role instead of the global union
     * UserInfoEngine.Instance.RegisterApplicationAccessFilter((appId, defaultAccess, user) => {
     *   const tenantRoleID = user.TenantContext?.roleID;
     *   if (!tenantRoleID) return defaultAccess; // no tenant context — fall back to default
     *   const appRoles = UserInfoEngine.Instance.ApplicationRoles
     *     .filter(ar => UUIDsEqual(ar.ApplicationID, appId));
     *   if (appRoles.length === 0) return true; // open access
     *   return appRoles.some(ar => UUIDsEqual(ar.RoleID, tenantRoleID) && ar.CanAccess);
     * });
     * ```
     */
    RegisterApplicationAccessFilter(filter: ApplicationAccessFilter | null): void;
    /**
     * Register a custom filter for application admin checks. The filter is
     * called by `UserCanAdminApplication()` after the default global role check.
     * It receives the default result and can override it based on custom logic.
     *
     * Only one filter can be registered at a time. Calling this again replaces
     * the previous filter. Pass `null` to remove the filter.
     */
    RegisterApplicationAdminFilter(filter: ApplicationAdminFilter | null): void;
    /**
     * Checks if the current user's roles grant access to the application.
     * If no ApplicationRole records exist for the app, access is open (backwards compatible).
     * If records exist, user must have at least one role with CanAccess=1.
     */
    UserHasApplicationAccess(applicationId: string): boolean;
    /**
     * Checks if the current user can administer a specific application.
     * Requires an explicit ApplicationRole record with CanAdmin=1.
     */
    UserCanAdminApplication(applicationId: string): boolean;
    /**
     * Check if an application is inactive in the system metadata.
     * @param applicationId - The application ID to check
     */
    IsApplicationInactive(applicationId: string): boolean;
    /**
     * Get application info by ID from metadata.
     * @param applicationId - The application ID to find
     */
    GetApplicationInfo(applicationId: string): ApplicationInfo | undefined;
    /**
     * Find application info by path or name (case-insensitive).
     * @param pathOrName - The path or name to search for
     */
    FindApplicationByPathOrName(pathOrName: string): ApplicationInfo | undefined;
    /**
     * Force refresh all user data
     * @param contextUser - Optional user context for server-side use
     */
    Refresh(contextUser?: UserInfo): Promise<void>;
    /**
     * Get only the active user applications (IsActive = true)
     */
    get ActiveUserApplications(): MJUserApplicationEntity[];
    /**
     * Check if user has a specific application installed (has UserApplication record)
     * @param applicationId - The application ID to check
     */
    HasApplication(applicationId: string): boolean;
    /**
     * Check if user has a specific application active (installed AND IsActive = true)
     * @param applicationId - The application ID to check
     */
    HasActiveApplication(applicationId: string): boolean;
    /**
     * Install an application for the current user by creating a UserApplication record.
     * The new record is automatically added to the cached UserApplications array.
     * @param applicationId - The application ID to install
     * @param contextUser - Optional user context for server-side use
     * @returns The newly created MJUserApplicationEntity, or null if failed
     */
    InstallApplication(applicationId: string, contextUser?: UserInfo): Promise<MJUserApplicationEntity | null>;
    /**
     * Enable a disabled application for the current user (set IsActive = true).
     * @param applicationId - The application ID to enable
     * @param contextUser - Optional user context for server-side use
     * @returns true if successful, false otherwise
     */
    EnableApplication(applicationId: string, contextUser?: UserInfo): Promise<boolean>;
    /**
     * Disable an application for the current user (set IsActive = false).
     * This does not delete the UserApplication record, just deactivates it.
     * @param applicationId - The application ID to disable
     * @param contextUser - Optional user context for server-side use
     * @returns true if successful, false otherwise
     */
    DisableApplication(applicationId: string, contextUser?: UserInfo): Promise<boolean>;
    /**
     * Uninstall an application by deleting the UserApplication record.
     * @param applicationId - The application ID to uninstall
     * @param contextUser - Optional user context for server-side use
     * @returns true if successful, false otherwise
     */
    UninstallApplication(applicationId: string, contextUser?: UserInfo): Promise<boolean>;
    /**
     * Create default UserApplication records for apps marked with DefaultForNewUser=true.
     * This is called automatically when a user has no UserApplication records.
     *
     * This method is safe to call multiple times concurrently - it will return the same
     * promise if already in progress, and will skip apps that already have UserApplication records.
     *
     * @param contextUser - Optional user context for server-side use
     * @returns Array of created MJUserApplicationEntity records
     */
    CreateDefaultApplications(contextUser?: UserInfo): Promise<MJUserApplicationEntity[]>;
    /**
     * Checks the database directly for this user's UserApplication records.
     * If the DB has records but our in-memory cache is empty (load failure),
     * repairs the cache and emits a property change so subscribers update.
     * @returns The DB records if repair occurred, empty array otherwise
     */
    private repairUserApplicationsFromDatabase;
    /**
     * Internal implementation of CreateDefaultApplications.
     * Separated to allow the public method to manage the promise state.
     */
    private doCreateDefaultApplications;
    /**
     * Get all notification preferences for the current user
     */
    get NotificationPreferences(): MJUserNotificationPreferenceEntity[];
    GetUserPreferenceForType(userId: string, typeId: string): MJUserNotificationPreferenceEntity | undefined;
    /**
     * Get current user's preference for a specific notification type
     */
    GetCurrentUserPreferenceForType(typeId: string): MJUserNotificationPreferenceEntity | undefined;
    /**
     * Get all notification types.
     * Notification types are global (not user-specific) and define the available notification categories.
     */
    get NotificationTypes(): MJUserNotificationTypeEntity[];
}
//# sourceMappingURL=UserInfoEngine.d.ts.map