import { Observable } from 'rxjs';
import * as i0 from '@angular/core';
import { Type, EnvironmentProviders } from '@angular/core';

/**
 * Represents an action with no payload.
 *
 * @returns `undefined` — used as a placeholder for actions without data.
 */
type EmptyPayloadFn = () => undefined;
/**
 * Function that receives and returns a typed payload.
 *
 * @template T - The payload type.
 * @param payload - The input data.
 * @returns The same payload.
 */
type ValuePayloadFn<T> = (payload: T) => T;
/**
 * Defines a payload function based on the payload type:
 * - If `T` is `undefined`, resolves to `EmptyPayloadFn`.
 * - Otherwise, resolves to `ValuePayloadFn<T>`.
 *
 * @template T - Payload type.
 */
type SingleAction<T> = T extends undefined ? EmptyPayloadFn : ValuePayloadFn<T>;
/**
 * Base structure for all actions.
 *
 * @property type - The action type string.
 * @property payload - Optional data attached to the action.
 */
type Action = {
    type: string;
    payload?: any;
};
/**
 * Converts a CamelCase or PascalCase string to snake_case.
 *
 * @template S - Input string type.
 *
 * @example
 * type A = CamelToSnakeCase<'loadFailure'> // 'load_failure'
 * type B = CamelToSnakeCase<'UserLogin'>   // 'user_login'
 */
type CamelToSnakeCase<S extends string> = S extends `${infer Head}${infer Tail}` ? Tail extends Uncapitalize<Tail> ? `${Lowercase<Head>}${CamelToSnakeCase<Tail>}` : `${Lowercase<Head>}_${CamelToSnakeCase<Tail>}` : S;

/**
 * Represents an empty payload for actions without data.
 *
 * @returns `undefined`
 */
declare const emptyPayload: EmptyPayloadFn;
/**
 * Creates a typed identity function for payloads.
 *
 * Useful to define payload handlers with a specific type.
 *
 * @template T - The expected payload type.
 * @returns A function that returns the same payload it receives.
 */
declare function payload<T>(): ValuePayloadFn<T>;
/**
 * Extracts the action type string from an action creator or object.
 *
 * @param action - Either an action creator (function with `.type`) or an action object.
 * @returns The `type` string.
 *
 * @example
 * ofType(someActionCreator) // 'SOME_ACTION'
 * ofType({ type: 'MY_ACTION' }) // 'MY_ACTION'
 */
declare function ofType<T extends (...args: any[]) => Action>(action: T): string;
declare function ofType(action: {
    type: string;
}): string;

/**
 * Defines a group of related actions with a common source
 *
 * This function provides a convenient way to define action groups without
 * directly injecting the ActionService
 *
 * @param config - Object containing source prefix and events map
 * @returns An object with action creators for each event
 */
declare function defineActionsGroup<Source extends string, Events extends Record<string, SingleAction<any>>>(config: {
    source: Source;
    events: Events;
}): { [K in keyof Events]: Events[K] extends EmptyPayloadFn ? () => {
    type: `${Uppercase<Source>}_${Uppercase<CamelToSnakeCase<string & K>>}`;
} : (payload: Parameters<Events[K]>[0]) => {
    type: `${Uppercase<Source>}_${Uppercase<CamelToSnakeCase<string & K>>}`;
    payload: Parameters<Events[K]>[0];
}; };
/**
 * Defines a single action with a source prefix
 *
 * This function provides a convenient way to define a single action without
 * directly injecting the ActionService
 *
 * @param source - Source prefix for the action type
 * @param payload - Payload handler function
 * @returns An object with an action creator
 */
declare function defineSingleAction<Source extends string, ActionPayload>(source: Source, payload: SingleAction<ActionPayload>): {
    action: ActionPayload extends undefined ? () => {
        type: `${Source}_ACTION`;
    } : (payload: ActionPayload) => {
        type: `${Source}_ACTION`;
        payload: ActionPayload;
    };
};

type SWEffects = Promise<Observable<Action> | Action | Action[] | void> | Observable<Action | Action[]> | Action | Action[] | void;

/**
 * Registers an effect that listens to a specific action and executes a handler.
 *
 * @param action - The action creator function.
 * @param handler - A function called when the action is dispatched.
 * - Receives the payload if the action defines one.
 * - Can return an action, array of actions, observable, or promise.
 */
declare function createEffect<T extends (payload: any) => Action>(action: T, handler: (payload: Parameters<T>[0]) => SWEffects): void;
/**
 * Registers an effect for an action without payload.
 *
 * @param action - Action creator with no payload.
 * @param handler - Function executed when the action is dispatched.
 */
declare function createEffect(action: () => Action, handler: () => SWEffects): void;

/**
 * Waits for all currently pending effects to resolve.
 *
 * This function ensures that all side effects triggered by actions are completed
 * before continuing with the execution flow.
 *
 * @returns A promise that resolves when all pending effects are completed.
 */
declare function waitForAllEffects(): Promise<void>;
/**
 * Waits for pending effects associated with a specific action type to resolve.
 *
 * Useful for scenarios where you need to wait for effects triggered by a particular
 * action before proceeding.
 *
 * @param actionType - The action type whose effects should be waited for.
 * @returns A promise that resolves when all pending effects for the specified action type are completed.
 */
declare function waitForEffect(actionType: string): Promise<void>;

/**
 * Interface representing an updator for state management.
 *
 * The `IUpdator` holds the current state and a registry of functions
 * (updators) that can modify that state based on different action types.
 *
 * @template S - The type of the state.
 */
interface IUpdator<S> {
    /**
     * The current state that the updators will modify.
     */
    readonly state: S;
    /**
     * A registry of updators, where each action type is associated with a function
     * that modifies the state.
     */
    readonly updators: UpdatorGlobalRegistry<S>;
}
/**
 * Type representing a function that updates the state based on an action.
 *
 * @template S - The type of the state.
 * @template P - The type of the payload (optional).
 *
 * @param state - The current state to be updated.
 * @param payload - The data to modify the state (optional).
 */
type Updator<S, P = any> = (state: S, payload?: P) => void;
/**
 * A registry of updators, where each action type is mapped to an `Updator` function.
 *
 * The key is the action type (usually a string), and the value is the corresponding
 * function that modifies the state when the action is dispatched.
 *
 * @template S - The type of the state.
 */
interface UpdatorGlobalRegistry<S> {
    /**
     * Maps action types to their corresponding `Updator` function.
     *
     * The key is an action type, and the value is an `Updator` that modifies the state.
     */
    [actionType: string]: Updator<S>;
}

/**
 * Registers a local updater for a given manager context.
 *
 * This function should be used within an Angular injection context (e.g. during component initialization).
 *
 * @template S - The state type handled by the updater.
 * @param {object} manager - The local context object (e.g., a component or a service) to associate the updater with.
 * @param {IUpdator<S>} updator - The updater instance defining actions and their update logic for the given state.
 */
declare function registerLocalUpdator<S>(manager: object, updator: IUpdator<S>): void;

/**
 * Dispatches an action with optional updator registration.
 *
 * This function provides a flexible way to dispatch actions:
 * - If only an action is provided, it will be dispatched through the ActionDispatcher
 * - If an updator is also provided, it will be registered (if needed) and used to update state
 *
 * @template T - The action type.
 * @template S - The state type (inferred from updator if provided).
 * @param action - The action to dispatch.
 * @param updator - Optional updator to handle state updates for this action.
 */
declare function dispatch<T extends Action>(action: T, context?: object): void;
declare function dispatch<T extends Action, S>(action: T, updator: IUpdator<S>): void;

/**
 * Asynchronously dispatches an action and waits for effects to complete.
 *
 * Similar to `dispatch`, but returns a Promise that resolves when all associated
 * effects are completed. Supports both global and local updators.
 *
 * @template T - The action type.
 * @template S - The state type (inferred from updator if provided).
 * @param action - The action to dispatch.
 * @param updator - Optional updator to handle state updates for this action.
 * @returns A Promise that resolves when all effects for this action are completed.
 */
declare function dispatchAsync<T extends Action>(action: T, context?: object): Promise<void>;
declare function dispatchAsync<T extends Action, S>(action: T, updator: IUpdator<S>): Promise<void>;

declare function provideStatewise(): i0.EnvironmentProviders;

/**
 * Registers and instantiates a list of effect classes at application startup.
 *
 * @param effectClasses - Array of effect class types to initialize.
 * @returns EnvironmentProviders to include in your application bootstrap.
 */
declare function provideEffects(effectClasses: Type<any>[]): EnvironmentProviders;

/**
 * Registers an array of updators globally at application startup.
 *
 * This function provides a way to register state updators during the Angular
 * application initialization phase, making them available throughout the application
 * without needing to register them with each dispatch call.
 *
 * @param updators - An array of Updator class to be registered globally.
 * @returns Angular EnvironmentProviders to be included in your application bootstrap.
 *
 */
declare function provideUpdators(updatorClasses: Type<IUpdator<any>>[]): EnvironmentProviders;

export { createEffect, defineActionsGroup, defineSingleAction, dispatch, dispatchAsync, emptyPayload, ofType, payload, provideEffects, provideStatewise, provideUpdators, registerLocalUpdator, waitForAllEffects, waitForEffect };
export type { IUpdator, UpdatorGlobalRegistry as UpdatorRegistry };
