import { INotifier, NotificationAlign, NotificationCallProps, NotificationContent, NotificationReturn } from "@etsoo/notificationbase";
import { ApiDataError, IApi, IPData } from "@etsoo/restclient";
import { DataTypes, DateUtils, ErrorData, ErrorType, IActionResult, IStorage, ListType, ListType1 } from "@etsoo/shared";
import { AddressRegion } from "../address/AddressRegion";
import { IUser } from "../state/User";
import { IAppSettings } from "./AppSettings";
import { UserRole } from "./UserRole";
import { EntityStatus } from "../business/EntityStatus";
import { Currency } from "../business/Currency";
import { ExternalEndpoint } from "./ExternalSettings";
import { ApiRefreshTokenDto } from "../api/dto/ApiRefreshTokenDto";
import { ApiRefreshTokenRQ } from "../api/rq/ApiRefreshTokenRQ";
/**
 * Detect IP callback interface
 */
export interface IDetectIPCallback {
    (): void;
}
/**
 * Navigate options
 */
export interface NavigateOptions {
    replace?: boolean;
    state?: any;
}
/**
 * Refresh token result type
 * array means success, false means failed but no any message
 * other cases means failed with differnet message
 */
export type RefreshTokenResult<R> = IActionResult | [string | null, R];
/**
 * Format result custom type
 */
export type FormatResultCustom = {
    title?: string;
    type?: string;
    field?: string;
};
/**
 * Format result custom callback type
 */
export type FormatResultCustomCallback = ((data: FormatResultCustom) => string | null | undefined) | boolean;
/**
 * Login parameters
 */
export type AppLoginParams = {
    /**
     * Login parameters to pass
     */
    params?: DataTypes.SimpleObject & {
        /**
         * Try login with cached refresh token
         */
        tryLogin?: boolean;
    };
    /**
     * Don't cache current URL instead of the default page
     */
    removeUrl?: boolean;
    /**
     * Show loading bar or not
     */
    showLoading?: boolean;
};
/**
 * App try login parameters
 */
export type AppTryLoginParams = AppLoginParams & {
    /**
     * Callback on failure
     * @param type Failure type
     */
    onFailure?: (type: string) => void;
    /**
     * Callback on success
     */
    onSuccess?: () => void;
};
/**
 * Refresh token props
 */
export interface RefreshTokenProps {
    /**
     * Refresh token
     */
    token?: string;
    /**
     * API URL
     */
    api?: string;
    /**
     * Show loading bar or not
     */
    showLoading?: boolean;
    /**
     * Header token field name
     */
    tokenField?: string;
}
/**
 * App fields
 */
export declare const appFields: readonly ["headerToken", "serversideDeviceId", "deviceId", "devices", "devicePassphrase", "cachedUrl", "embedded", "keepLogin"];
/**
 * Basic type template
 */
export type IAppFields = {
    [key in (typeof appFields)[number]]: string;
};
/**
 * Application interface, for generic version, see ICoreApp
 */
export interface IApp {
    /**
     * Settings
     */
    readonly settings: IAppSettings;
    /**
     * Default region
     */
    readonly defaultRegion: AddressRegion;
    /**
     * Fields
     */
    readonly fields: IAppFields;
    /**
     * API, not recommend to use it directly in code, wrap to separate methods
     */
    readonly api: IApi;
    /**
     * Notifier
     */
    readonly notifier: INotifier<unknown, NotificationCallProps>;
    /**
     * Label delegate
     */
    readonly labelDelegate: <T = string>(key: string) => T | undefined;
    /**
     * Culture, like zh-CN
     */
    readonly culture: string;
    /**
     * Currency, like USD for US dollar
     */
    readonly currency: Currency;
    /**
     * Device id
     */
    readonly deviceId: string;
    /**
     * Country or region, like CN
     */
    readonly region: string;
    /**
     * Storage
     */
    readonly storage: IStorage;
    /**
     * Is current authorized
     */
    readonly authorized: boolean;
    /**
     * Is the app ready
     */
    readonly isReady: boolean;
    /**
     * Is trying to login
     */
    readonly isTryingLogin: boolean;
    /**
     * Application name
     */
    readonly name: string;
    /**
     * Pending actions
     */
    readonly pendings: (() => any)[];
    /**
     * Is debug mode
     */
    readonly debug: boolean;
    /**
     * Is embedded mode
     */
    readonly embedded: boolean;
    /**
     * Cached URL
     */
    cachedUrl: string | undefined | null;
    /**
     * Keep login or not
     */
    keepLogin: boolean;
    /**
     * IP data
     */
    ipData?: IPData;
    /**
     * User data
     */
    userData?: IUser;
    /**
     * Search input element
     */
    searchInput?: HTMLInputElement;
    /**
     * Is screen size down 'sm'
     */
    smDown?: boolean;
    /**
     * Is screen size up 'md'
     */
    mdUp?: boolean;
    /**
     * Add root (homepage) to the URL
     * @param url URL to add
     * @returns Result
     */
    addRootUrl(url: string): string;
    /**
     * Add scheduled task
     * @param task Task, return false to stop
     * @param interval Interval in milliseconds
     */
    addTask(task: () => PromiseLike<void | false>, interval: number): void;
    /**
     * Alert result
     * @param result Result message
     * @param callback Callback
     */
    alertResult(result: string, callback?: NotificationReturn<void>): void;
    /**
     * Alert action result
     * @param result Action result
     * @param callback Callback
     * @param forceToLocal Force to local labels
     */
    alertResult(result: IActionResult, callback?: NotificationReturn<void>, forceToLocal?: FormatResultCustomCallback): void;
    /**
     * Authorize
     * @param token New access token
     * @param schema Access token schema
     * @param refreshToken Refresh token
     */
    authorize(token?: string, schema?: string, refreshToken?: string): void;
    /**
     * Change country or region
     * @param region New country or region
     */
    changeRegion(region: string | AddressRegion): void;
    /**
     * Change culture
     * @param culture New culture definition
     */
    changeCulture(culture: DataTypes.CultureDefinition): Promise<DataTypes.StringRecord>;
    /**
     * Check the action result is about device invalid
     * @param result Action result
     * @returns true means device is invalid
     */
    checkDeviceResult(result: IActionResult): boolean;
    /**
     * Check language is supported or not
     * @param language Language
     * @returns Result
     */
    checkLanguage(language?: string): string;
    /**
     * Check current app is in same session
     * @param callback Callback
     */
    checkSession(callback: (isSame: boolean) => Promise<void | false>): Promise<void>;
    /**
     * Clear cache data
     */
    clearCacheData(): void;
    /**
     * Clear cached token
     */
    clearCacheToken(): void;
    /**
     * Clear device id
     */
    clearDeviceId(): void;
    /**
     * Clear user session
     */
    clearSession(): void;
    /**
     * Create API client, override to implement custom client creation by name
     * @param name Client name
     * @param item External endpoint item
     * @returns Result
     */
    createApi(name: string, item: ExternalEndpoint, refresh?: (api: IApi, rq: ApiRefreshTokenRQ) => Promise<[string, number] | undefined>): IApi;
    /**
     * Decrypt message
     * @param messageEncrypted Encrypted message
     * @param passphrase Secret passphrase
     * @returns Pure text
     */
    decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
    /**
     * Enhanced decrypt message
     * @param messageEncrypted Encrypted message
     * @param passphrase Secret passphrase
     * @param durationSeconds Duration seconds, <= 12 will be considered as month
     * @returns Pure text
     */
    decryptEnhanced(messageEncrypted: string, passphrase?: string, durationSeconds?: number): string | undefined;
    /**
     * Detect IP data, call only one time
     * @param callback Callback will be called when the IP is ready
     */
    detectIP(callback?: IDetectIPCallback): void;
    /**
     * Dispose the application
     */
    dispose(): void;
    /**
     * Download file
     * @param stream File stream
     * @param filename File name
     * @param callback callback
     */
    download(stream: ReadableStream, filename?: string, callback?: (success: boolean | undefined) => void): Promise<void>;
    /**
     * Encrypt message
     * @param message Message
     * @param passphrase Secret passphrase
     * @param iterations Iterations, 1000 times, 1 - 99
     * @returns Result
     */
    encrypt(message: string, passphrase?: string, iterations?: number): string;
    /**
     * Enhanced encrypt message
     * @param message Message
     * @param passphrase Secret passphrase
     * @param iterations Iterations, 1000 times, 1 - 99
     * @returns Result
     */
    encryptEnhanced(message: string, passphrase?: string, iterations?: number): string;
    /**
     * Exchange token data
     * @param api API
     * @param token Core system's refresh token to exchange
     * @returns Result
     */
    exchangeToken(api: IApi, token: string): Promise<void>;
    /**
     * Exchange intergration tokens for all APIs
     * @param coreData Core system's token data to exchange
     */
    exchangeTokenAll(coreData: ApiRefreshTokenDto): void;
    /**
     * Format date to string
     * @param input Input date
     * @param options Options
     * @param timeZone Time zone
     * @returns string
     */
    formatDate(input?: Date | string, options?: DateUtils.FormatOptions, timeZone?: string): string | undefined;
    /**
     * Format action
     * @param action Action
     * @param target Target name or title
     * @param items More items
     * @returns Result
     */
    formatAction(action: string, target: string, ...items: string[]): string;
    /**
     * Format error
     * @param error Error
     * @returns Error message
     */
    formatError(error: ApiDataError): string;
    /**
     * Format money number
     * @param input Input money number
     * @param isInteger Is integer
     * @param options Options
     * @returns Result
     */
    formatMoney(input: number | bigint, isInteger?: boolean, options?: Intl.NumberFormatOptions): string;
    /**
     * Format number
     * @param input Input number
     * @param options Options
     * @returns Result
     */
    formatNumber(input: number | bigint, options?: Intl.NumberFormatOptions): string;
    /**
     * Format as full name
     * @param familyName Family name
     * @param givenName Given name
     */
    formatFullName(familyName: string | undefined | null, givenName: string | undefined | null): string;
    /**
     * Format result text
     * @param result Action result
     * @param forceToLocal Force to local labels
     * @returns Message
     */
    formatResult(result: IActionResult, forceToLocal?: FormatResultCustomCallback): string;
    /**
     * Fresh countdown UI
     * @param callback Callback
     */
    freshCountdownUI(callback?: () => PromiseLike<unknown>): void;
    /**
     * Get culture resource
     * @param key key
     * @returns Resource
     */
    get<T = string>(key: string): T | undefined;
    /**
     * Get multiple culture labels
     * @param keys Keys
     */
    getLabels<T extends string>(...keys: T[]): {
        [K in T]: string;
    };
    /**
     * Get bool items
     * @returns Bool items
     */
    getBools(): ListType1[];
    /**
     * Get cached token
     * @returns Cached token
     */
    getCacheToken(): string | undefined;
    /**
     * Get data privacies
     * @returns Result
     */
    getDataPrivacies(): ListType[];
    /**
     * Get enum item number id list
     * @param em Enum
     * @param prefix Label prefix or callback
     * @param filter Filter
     * @returns List
     */
    getEnumList<E extends DataTypes.EnumBase = DataTypes.EnumBase>(em: E, prefix: string | ((key: string) => string), filter?: (id: E[keyof E], key: keyof E & string) => E[keyof E] | undefined): ListType[];
    /**
     * Get enum item string id list
     * @param em Enum
     * @param prefix Label prefix or callback
     * @param filter Filter
     * @returns List
     */
    getEnumStrList<E extends DataTypes.EnumBase = DataTypes.EnumBase>(em: E, prefix: string | ((key: string) => string), filter?: ((id: E[keyof E], key: keyof E & string) => E[keyof E] | undefined) | E[keyof E][]): ListType1[];
    /**
     * Get region label
     * @param id Region id
     * @returns Label
     */
    getRegionLabel(id: string): string;
    /**
     * Get all regions
     * @returns Regions
     */
    getRegions(): AddressRegion[];
    /**
     * Get role label
     * @param role Role value
     * @param joinChar Join char
     * @returns Label(s)
     */
    getRoleLabel(role: number | null | undefined, joinChar?: string): string;
    /**
     * Get roles
     * @param role Combination role value, null for all roles
     */
    getRoles(role?: number): ListType[];
    /**
     * Get status label
     * @param status Status value
     */
    getStatusLabel(status: number | null | undefined): string;
    /**
     * Get status list
     * @param ids Limited ids
     * @returns list
     */
    getStatusList(ids?: EntityStatus[]): ListType[];
    /**
     * Get refresh token from response headers
     * @param rawResponse Raw response from API call
     * @param tokenKey Refresh token key
     * @returns response refresh token
     */
    getResponseToken(rawResponse: any, tokenKey: string): string | null;
    /**
     * Get time zone
     * @returns Time zone
     */
    getTimeZone(): string;
    /**
     * Hash message, SHA3 or HmacSHA512, 512 as Base64
     * https://cryptojs.gitbook.io/docs/
     * @param message Message
     * @param passphrase Secret passphrase
     */
    hash(message: string, passphrase?: string): string;
    /**
     * Hash message Hex, SHA3 or HmacSHA512, 512 as Base64
     * https://cryptojs.gitbook.io/docs/
     * @param message Message
     * @param passphrase Secret passphrase
     */
    hashHex(message: string, passphrase?: string): string;
    /**
     * Check user has the minimum role permission or not
     * @param role Minumum role
     * @returns Result
     */
    hasMinPermission(role: UserRole): boolean;
    /**
     * Check user has the specific role permission or not
     * @param roles Roles to check
     * @returns Result
     */
    hasPermission(roles: number | UserRole | number[] | UserRole[]): boolean;
    /**
     * Init call
     * @param callback Callback
     * @param resetKeys Reset all keys first
     * @returns Result
     */
    initCall(callback?: (result: boolean) => void, resetKeys?: boolean): Promise<void>;
    /**
     * Is admin user
     * @returns Result
     */
    isAdminUser(): boolean;
    /**
     * Is Finance user
     * @returns Result
     */
    isFinanceUser(): boolean;
    /**
     * Is Manager user
     * @returns Result
     */
    isManagerUser(): boolean;
    /**
     * Is valid password, override to implement custom check
     * @param password Input password
     */
    isValidPassword(password: string): boolean;
    /**
     * Load URL
     * @param url URL
     * @param targetOrigin Target origin
     */
    loadUrl(url: string, targetOrigin?: string): void;
    /**
     * Navigate to Url or delta
     * @param url Url or delta
     * @param options Options
     */
    navigate<T extends number | string | URL>(to: T, options?: T extends number ? never : NavigateOptions): void;
    /**
     * Notify user with success message
     * @param message Success message
     * @param callback Popup close callback
     */
    ok(callback?: NotificationReturn<void>, message?: NotificationContent<unknown>): void;
    /**
     * Callback where exit a page
     */
    pageExit(): void;
    /**
     * Refresh token
     * @param props Props
     * @param callback Callback
     */
    refreshToken(props?: RefreshTokenProps, callback?: (result?: boolean | IActionResult) => boolean | void): Promise<void>;
    /**
     * Save refresh token to cache
     * @param token Refresh token
     */
    saveCacheToken(token: string | undefined): void;
    /**
     * Setup Api error handler
     * @param api Api
     * @param handlerFor401 Handler for 401 error
     */
    setApiErrorHandler(api: IApi, handlerFor401?: boolean | (() => Promise<void>)): void;
    /**
     * Setup Api loading
     * @param api Api
     */
    setApiLoading(api: IApi): void;
    /**
     * Setup frontend logging
     * @param action Custom action
     * @param preventDefault Is prevent default action
     */
    setupLogging(action?: (data: ErrorData) => void | Promise<void>, preventDefault?: ((type: ErrorType) => boolean) | boolean): void;
    /**
     * Signout, with userLogout and toLoginPage
     * @param action Callback
     */
    signout(action?: () => void | boolean): Promise<void>;
    /**
     * Persist settings to source when application exit
     */
    persist(): void;
    /**
     * Go to the login page
     * @param data Login parameters
     */
    toLoginPage(data?: AppLoginParams): void;
    /**
     * Try login, returning false means is loading
     * UI get involved while refreshToken not intended
     * @param data Login parameters
     */
    tryLogin(data?: AppLoginParams): Promise<boolean>;
    /**
     * Update API token and expires
     * @param name Api name
     * @param token Refresh token
     * @param seconds Access token expires in seconds
     */
    updateApi(name: string, token: string | undefined, seconds: number): void;
    /**
     * Update embedded status
     * @param embedded New embedded status
     */
    updateEmbedded(embedded?: boolean): void;
    /**
     * User login
     * @param user User data
     * @param refreshToken Refresh token
     */
    userLogin(user: IUser, refreshToken: string): void;
    /**
     * User logout
     * @param clearToken Clear refresh token or not
     * @param noTrigger No trigger for state change
     */
    userLogout(clearToken: boolean, noTrigger?: boolean): void;
    /**
     * User unauthorized
     */
    userUnauthorized(): void;
    /**
     * Show warning message
     * @param message Message
     * @param align Align, default as TopRight
     */
    warning(message: NotificationContent<unknown>, align?: NotificationAlign): void;
}
