import { Observable } from "rxjs";
import { INavigationBarTabSaveOptions } from "./shell-tabs-lifecycle-api";
import { RequiredResourcesExpression } from "../config/config-api";
export interface WebElementData {
    elementName: string;
    doNotReuse?: boolean;
}
export interface INavigationBarTabs<D1 = any, D2 = D1> {
    primary: INavigationBarTab<D1>;
    secondary?: INavigationBarTab<D2>;
}
export interface INavigationBarTab<D = {
    [key: string]: any;
}, SecondaryData = D> {
    /** Unique tab identifier */
    id: string;
    /** URL relative to shell root (e.g., /user/123) - must start with a forward slash */
    routeUrl: string;
    /** Label for the tab, can be a string or resource key (if isLabelResourceKey is true) */
    label: string;
    /** Weight used during sorting to order the tabs; defaults to the order in which tabs were added.
     * This doesn't refer to array index, as many tabs can have the same value, including negatives and fractions.
     */
    sortIndex?: number;
    /** When true, uses resourceService.get to resolve INavigationBarTab.label */
    isLabelResourceKey?: boolean;
    /** Font icon */
    icon?: string;
    /** Image URL */
    img?: string;
    /** aria-controls ID */
    controlsId?: string;
    /** List of secondary tabs displayed under the top-level tab */
    secondaryTabs?: Array<ISecondaryNavigationBarTab<SecondaryData>>;
    /** Currently selected secondary tab */
    selectedSecondaryTab?: ISecondaryNavigationBarTab<SecondaryData>;
    /** Callback to configure save confirmation actions on close */
    getSaveOptions?(tab: INavigationBarTab): INavigationBarTabSaveOptions | undefined;
    /** Callback executed when tab is removed */
    onClose?(tab: INavigationBarTab): Promise<boolean> | Observable<boolean> | boolean;
    /** Mark tab as having unsaved changes */
    dirty?: boolean;
    /** Visually disable and make tab unselectable */
    disabled?: boolean;
    /** Visually hide tab and make it unselectable */
    hidden?: boolean;
    /** Exclude tab from appearing in the navigation bar system tab menu */
    excludedFromSystemMenu?: boolean;
    /** Visually hide secondary tabs bar for this tab */
    hideSecondaryTabs?: boolean;
    /** Indicate that the tab is associated with a new object being created */
    creating?: boolean;
    /** Any additional data to be associated with the tab */
    data?: D;
}
export type ISecondaryNavigationBarTab<D = {
    [key: string]: any;
}> = Omit<INavigationBarTab<D>, "secondaryTabs" | "selectedSecondaryTab">;
export interface SviShellTabData {
    /**
     * Required user capabilities for the tab.
     * If unmet, the tab is hidden and cannot be navigated to.
     * @example
     * { or: ["svi.administration.alerts", "svi.vsd.flow.view"] }
     */
    requiredCapabilities?: RequiredResourcesExpression;
    /**
     * REST APIs required by the tab's content.
     * If unavailable, the tab is hidden and cannot be navigated to.
     * @example
     * { and: ["svi-alert", "documentGeneratorAdapter"] }
     */
    requiredServices?: RequiredResourcesExpression;
    /**
     * Set to true if the tab visibility depends on CAS being enabled.
     * If CAS is enabled, the tab will show. If CAS is disabled, the tab will be
     * hidden and cannot be navigated to. If set to false/undefined (default),
     * the tab will show regardless of whether CAS is enabled.
     */
    CASSensitive?: boolean;
    [key: string]: any;
}
export interface ExternalTabConfig<T = SviShellTabData, P = any> {
    /**
     * Will try to place at this index, can be negative, fraction, etc. to put before/between existing tabs.
     */
    sortIndex?: number;
    /**
     * Finds TabId, and adds this as a secondaryTab to that tab.
     */
    mainTabId?: string;
    /**
     * This is the element/tag name that will be presented.
     */
    elementName: string;
    /**
     * This is the URL that the tab will be registered under.
     * Technically it's just a unique ID as this will be used to unregister a route and close any related tab(s).
     */
    configUrl: string;
    /**
     * Function to return {@link INavigationBarTab}. Remember routeUrl is from baseURL with a leading /.
     * fullUrl is the full URL that relates to the tab, useful when catching wildcards.
     * params is constructed as of /:param1/:param2, so {param1: string, param2: string}.
     * Be aware fullUrl/params will be undefined if buildOnRegister is true.
     */
    buildTab: (fullUrl?: string, params?: P) => INavigationBarTab<T>;
    /**
     * Add as a system tab. If left out will default to application tab, ignored if mainTabId is defined.
     */
    systemTab?: boolean;
    /**
     * Set this to true if you want the component to reset every time you navigate away.
     */
    doNotReuse?: boolean;
    /**
     * Set this to true if you want buildTab to run when registered (e.g. for a system tab that's always there).
     * If your buildTab takes params, this cannot be provided and must be assumed undefined.
     * A secondaryTab (one that has mainTabId) will be created regardless of this flag.
     */
    buildOnRegister?: boolean;
}
/**
 * This API provides functionality relating to the shell tabs.
 *
 * Accessed from the window at `window.sas.vi.shellTabs`.
 *
 * @example window.sas.vi.shellTabs.getSelectedTab();
 * @category API
 */
export interface ShellTabsApi<T = SviShellTabData> {
    /**
     * @method
     * @description This is used to expose any {@link PotentialTabItem} hooks on a component up to the Tab Service.
     * @param {any} context Pass "this".
     * @param {HTMLElement} nativeElement This will pass the ElementRef for the component.
     *
     *  onTabClose {@link OnTabClose}, optional, can be used to prevent closing of a tab or close async.
     *  onAttachTab {@link OnAttachTab}, will always trigger when currentNavigationBarTab is set.
     *  onAttachToolbar {@link TabWithToolbar}, optional, will set currentToolbar if there was a toolbar in the VI Router.
     *  onTabEnter {@link OnTabEnter}, optional, will trigger when tab is entered.
     *  onTabLeave {@link OnTabLeave}, optional, will trigger when tab is left.
     *  onTabSaveConfirm {@link OnTabSaveConfirm}, optional, basic dialog box can be created when closing a dirty tab.
     */
    createTabApiForElement: (context: any, nativeElement: HTMLElement) => void;
    /**
     * @method
     * @description Use this function to register new routes for tabs.
     * @param {ExternalTabConfig[]} tab See {@link ExternalTabConfig}.
     */
    registerExternalTabs: (tab: Array<ExternalTabConfig<T>>) => void;
    /**
     * @method
     * @description Use this function to remove routes added via registerTabFn.
     * @param {ExternalTabConfig[]} tabsToRemove See {@link ExternalTabConfig}.
     */
    unregisterExternalTabs: (tabsToRemove: Array<ExternalTabConfig<T>>) => void;
    /**
     * @method
     * @description This will return the current primary and secondary tabs.
     */
    getSelectedTab: () => {
        primaryTab: INavigationBarTab;
        secondaryTab?: INavigationBarTab;
    };
    /**
     * @method
     * @description This stream will track the current top-level tab.
     */
    selectedPrimaryTabChanged$: Observable<INavigationBarTab>;
    /**
     * @method
     * @description This stream will track the current second-level tab.
     */
    selectedSecondaryTabChanged$: Observable<INavigationBarTab | undefined>;
    /**
     * @method
     * @description This stream will update after any additions/removals to either system or application tabs.
     */
    openTabsChanged$: Observable<{
        systemTabs: INavigationBarTab[];
        applicationTabs: INavigationBarTab[];
    }>;
    /**
     * @method
     * @description This stream will emit any removed tabs.
     */
    tabRemoved$: Observable<INavigationBarTab>;
    /**
     * @method
     * @description Get Tab by ID.
     * @param [tabId] {string} This will be ID of an existing tab.
     */
    getTabById: (tabId: string) => INavigationBarTab | undefined;
    /**
     * @method
     * @description This will return a slice of the current system and application tabs.
     */
    getAllTabs: () => {
        system: INavigationBarTab[];
        application: INavigationBarTab[];
    };
    /**
     * @method
     * @description This will move user to the default tab.
     */
    selectDefaultTab: () => Promise<boolean>;
    /**
     * @method
     * @description This will attempt to open+select a matching INavigationBarTab and optional secondaryTab, returning false on failure.
     * In the event the tab doesn't exist already, it will add the tab assuming an appropriate route has been registered for it.
     * @param [tabToSelect] {INavigationBarTab} See {@link INavigationBarTab}.
     * @param [secondaryTab] {INavigationBarTab} See {@link INavigationBarTab}. If left undefined, this will select the previously
     * selected secondary tab of the primary tab or its first index secondary tab.
     */
    openTab: (tabToSelect: INavigationBarTab, secondaryTab?: INavigationBarTab) => Promise<boolean>;
    /**
     * @method
     * @description This will attempt to select a tab by its id, returning false on failure.
     * @param [tabId] {string} This will be ID of an existing tab.
     */
    selectTabById: (tabId: string) => Promise<boolean>;
    /**
     * @method
     * @description This will remove an application tab, if allowed, and will trigger any closing and saving logic beforehand.
     * @param [tabIdToRemove] {string} This will be ID of an existing tab.
     * @param [suppressNavigation] {boolean} Set suppressNavigation to true if you want to close a tab that isn't open.
     */
    removeApplicationTabById: (tabIdToRemove: string, suppressNavigation?: boolean) => Promise<boolean>;
    /**
     * @method
     * @description This will remove an existing application tab then replace with another. If {@link removeApplicationTabById} is unsuccessful this will fail.
     * Use case can be saving a tab which has a temporary ID, and reopening it with a saved payload.
     * @param [tabId] {string} This will be ID of an existing tab.
     * @param [newTab] {INavigationBarTab} See {@link INavigationBarTab}.
     *
     */
    replaceApplicationTab: (tabId: string, newTab: INavigationBarTab) => Promise<boolean>;
    /**
     * @method
     * @description This will run {@link removeApplicationTabById} on all tabs, will stop if any fail to close, will wait for each close to complete.
     */
    removeAllApplicationTabs: () => Promise<boolean>;
    /**
     * @method
     * @description This will run the same as {@link removeAllApplicationTabs}, but not on the provided tabIdToKeep.
     * @param [tabIdToKeep] {string}
     */
    removeOtherApplicationTabs: (tabIdToKeep?: string) => Promise<boolean>;
}
