import { AlContextProvider } from '@al/core';

/**
 * Describes the entry location, availability criteria, and prompt behaviors of a specific experience (for the purposes of this
 * type, and "experience" = a specific variation or common subset of a feature.
 */
export declare interface AlExperienceMapping {
    name: string;
    /**
     * A route or trigger that can be used to imperatively invoke the experience
     */
    entryRoute: AlRouteAction;
    /**
     * May be a boolean, a route condition, or an array of route conditions that determine when this experience should be enabled.
     */
    trigger: AlRouteCondition | AlRouteCondition[] | boolean;
    /**
     * If present and true, indicates the user can opt in or out of this experience, and their opt-in status should be "sticky."
     */
    optional?: boolean;
    /**
     * If provided, defines the zero state to provide when an experience isn't available.
     */
    unavailable?: {
        title: string | boolean;
        description: string | boolean;
        iconClass?: string;
        iconText?: string;
    };
    /**
     * Describes how related complementary/alternative experiences should be cross-referenced from this one.
     */
    crosslink?: {
        experienceId: string;
        strategy: "reroute" | "trigger" | "above-content";
        caption: string;
        trigger: string;
    }[];
}

/**
 * The unique members of this class have been consolidated into AlRouteCondition, leaving this interface a hollow shell.
 * Don't use it; it will be deprecated and removed in future versions.
 */
export declare interface AlExperienceToggle extends AlRouteCondition {
    empty_property?: boolean;
}

/**
 * @public
 *
 * This is a top-level interface for the structure of a schema document, which is a set of compiled menus and behavioral rules.
 */
export declare interface AlNavigationSchema {
    name: string;
    description: string;
    menus: {
        [menuId: string]: AlRouteDefinition;
    };
    namedRoutes: {
        [routeName: string]: AlRouteDefinition;
    };
    conditions: {
        [conditionId: string]: AlRouteCondition;
    };
}

/**
 *  @public
 *
 *  An AlRoute is an instantiated route definition, attached to a routing host, and capable of actually calculating target URLs based on context
 *  and handling navigation events.
 */
export declare class AlRoute {
    host: AlRoutingHost;
    definition: AlRouteDefinition;
    parent: AlRoute | undefined;
    static debug: boolean;
    static reCache: {
        [pattern: string]: RegExp | null;
    };
    caption: string;
    visible: boolean;
    enabled: boolean;
    locked: boolean;
    activated: boolean;
    children: AlRoute[];
    properties: {
        [property: string]: any;
    };
    baseHREF?: string;
    href?: string;
    constructor(host: AlRoutingHost, /* Link to the routing host, which exposes current routing context, routing parameters, and actions that influence the environment */ definition: AlRouteDefinition, /* The raw data of the route */ parent?: AlRoute | undefined);
    static link(host: AlRoutingHost, locationId: string, path: string, caption?: string): AlRoute;
    static trigger(host: AlRoutingHost, triggerName: string, caption?: string): AlRoute;
    /**
     * Sets an arbitrary property for the route
     */
    setProperty(propName: string, value: any): void;
    /**
     * Deletes a property.  If the immutable route definition contains the same property, it will be
     * restored.
     */
    deleteProperty(propName: string): void;
    /**
     * Retrieves a property.
     */
    getProperty(propName: string, defaultValue?: any): any;
    /**
     * Refreshes the state of a given route.  Internal refresh should be considered an extension of this method; the outer function
     * simply wraps the tree iteration process in exception handling.
     *
     * @param resolve - If true, forces the calculated href and visibility properties to be recalculated.
     *
     * @returns Returns true if the route (or one of its children) is activated, false otherwise.
     */
    refresh(resolve?: boolean): void;
    internalRefresh(resolve: boolean, state: AlRouteIterationState): boolean | undefined;
    evaluateRouteOptions(): boolean;
    /**
     * Disables a route
     */
    disable(): boolean;
    /**
     * "Executes" a route.  This invokes the `dispatch` method on whatever routing host was provided to the menu at load time.
     */
    dispatch(): void;
    /**
     * Retrieves the full URL for a route, if applicable.
     */
    toHref(): string;
    /**
     * Diagnostic method for logging the current hierarchy and state of a given navigational tree.  Excluded from unit test coverage because no production code should utilize it!
     */
    summarize(showAll?: boolean, depth?: number): string;
    /**
     *---- Helper Methods ---------------------------------------------
     */
    /**
     * Evaluates the HREF for an route with action type 'link'
     */
    evaluateHref(action: AlRouteAction): boolean;
    /**
     * Evaluates the activation state of the route
     */
    evaluateActivation(state: AlRouteIterationState): boolean;
    /**
     *  Evaluates an AlRouteCondition recursively.
     *
     *  Internally, the methods compiles boolean results of
     *      a) nested conditions
     *      b) route parameters or parameter expressions
     *      c) path matches
     *      d) entitlements or other externally calculated conditions
     *  And then uses a simple reducer to roll up all results based on the condition rule, which defaults to 'all'.
     */
    evaluateCondition(condition: AlRouteCondition | string | boolean): boolean;
    /**
     * Determine whether a route parameter test is true or not
     */
    evaluateParameterExpression(expression: string): boolean;
    /**
     * Determines whether a path pattern matches the current URL
     */
    evaluatePathMatch(pathMatches: string): boolean;
    /**
     * Retrieves the route's action, which may be a shared "named" route or embedded directly into the route's definition.
     */
    getRouteAction(): AlRouteAction | null;
    /**
     * Updates the route to use a specified action
     */
    setAction(action: AlRouteAction): void;
    /**
     * Updates the route to use a specific callback action.
     */
    setCallback(callback?: {
        (route: AlRoute, mouseEvent?: any): void;
    }): void;
    /**
     * Retrieves a nested child route by matching bookmarks, captions, IDs, or numerical indices.
     */
    findChild(idPath: string | string[]): AlRoute | null;
    /**
     * Generic method for recursing a menu hierarchy, using a callback to match the route.
     *
     * @param callback is a method that accepts a route (and optionally its definition) and returns
     *          `true` if the route is the correct one, in which case it is the result of the search method.
     *          `false` if the route is incorrect but its children should be iterated.
     *          `null` if the route is incorrect and its children should be ignored
     */
    search(matcher: {
        (route: AlRoute, definition?: AlRouteDefinition): boolean;
    }, enabledOnly?: boolean): AlRoute | undefined;
    /**
     * This method will return the deepest activated, childless route within its first activated child.  If this sounds obtuse,
     * it is -- but's it's important for determining the "cursor" menu item within a menu hierarchy.
     */
    getActivationCursor(): AlRoute | undefined;
    /**
     * This method uses the method above to generate a flat array of activated menu items, from top to bottom,
     * or undefined if no child of the given menu is activated.
     */
    getActivationCursorFlat(): AlRoute[] | undefined;
}

/**
 *  @public
 *  The action associated with a route.  These are only the most common properties.
 */
export declare interface AlRouteAction {
    /**
     *  What type of action does this route have?  Valid types are 'link', 'trigger', and 'callback'
     */
    type: string;
    /**
     * If the route action is 'link' (default), these properties indicate which application (location)
     * and route (path) OR url (fully qualified) the link should point to.
     */
    location?: string;
    path?: string;
    url?: string;
    /**
     * If the type of the action is 'trigger', this is the name of the event to be triggered.
     */
    trigger?: string;
    /**
     * If the type of the action is 'callback', this is the anonymous function that will be executed.
     */
    callback?: {
        (route: AlRoute, mouseEvent?: any): void;
    };
}

/**
 *  @public
 */
export declare interface AlRouteCondition {
    conditionId?: string;
    rule?: "any" | "all" | "none";
    conditions?: AlRouteCondition[];
    path_matches?: string;
    parameters?: string[];
    authentication?: boolean;
    entitlements?: string[];
    primaryEntitlements?: string[];
    environments?: string[];
    accounts?: string[];
    primaryAccounts?: string[];
    locations?: string[];
    primaryLocations?: string[];
    experiences?: string[];
    after?: string | number;
    before?: string | number;
}

/**
 *  @public
 *
 *  This is an abstract definition for a single menu item or menu container.
 */
export declare interface AlRouteDefinition {
    caption: string;
    id?: string;
    name?: string;
    bookmarkId?: string;
    properties?: {
        [property: string]: any;
    };
    action?: AlRouteAction | string;
    enabled?: AlRouteCondition | string | boolean;
    visible?: AlRouteCondition | string | boolean;
    matches?: string[];
    children?: AlRouteDefinition[];
    bubble?: boolean;
    isPublic?: boolean | null;
    options?: {
        visible?: AlRouteCondition | boolean;
        action: AlRouteAction | string;
    }[];
    activationRule?: "primary" | "inert";
}

/**
 * @private
 *
 * Utility class for menu tree refreshes and activation checks; mostly intended to avoid repetitive string manipulation :)
 */
declare class AlRouteIterationState {
    rootNode: AlRoute;
    depth: number;
    currentUrlNoParams: string;
    host: AlRoutingHost;
    constructor(rootNode: AlRoute);
}

/**
 * @public
 *
 * Any navigation host must provide these basic functions
 */
export declare interface AlRoutingHost {
    context: AlContextProvider;
    currentUrl: string;
    routeParameters: {
        [parameter: string]: string;
    };
    setRouteParameter(parameter: string, value: string): void;
    deleteRouteParameter(parameter: string): void;
    getRouteByName?(routeName: string): AlRouteDefinition;
    getConditionById(conditionId: string): AlRouteCondition | boolean;
    decorateHref?(route: AlRoute): void;
    setBookmark(bookmarkId: string, route: AlRoute): void;
    getBookmark(bookmarkId: string): AlRoute;
    dispatch(route: AlRoute, params?: {
        [param: string]: string;
    }): void;
    evaluate(condition: AlRouteCondition): boolean | boolean[];
}

export { }
