import type { Reducer } from 'react';
import { Observable, type Subscription } from 'rxjs';
import type { Action, ActionType, ExtractAction } from './types/actions';
import type { Flow, Effect } from './types/flow';
import type { ReducerWithInitialState } from './types/reducers';
/**
 * A specialized Observable that maintains internal state mutated by dispatching actions.
 *
 * Actions are processed sequentially by a reducer function to produce new state values.
 * Extends `Observable` so subscribers react to state changes over time.
 *
 * Inspired by Redux-style state management but built on top of RxJS, `FlowSubject`
 * combines a `BehaviorSubject` for state with a `Subject` for actions, providing
 * a reactive, observable state container.
 *
 * @template S - The state type managed by this subject.
 * @template A - The action type dispatched to this subject.
 *
 * @example
 * ```ts
 * import { FlowSubject, createReducer } from '@equinor/fusion-observable';
 *
 * type State = { count: number };
 * type Action = { type: 'increment' } | { type: 'decrement' };
 *
 * const reducer = createReducer<State, Action>({ count: 0 }, (builder) =>
 *   builder
 *     .addCase('increment', (state) => { state.count += 1; })
 *     .addCase('decrement', (state) => { state.count -= 1; }),
 * );
 *
 * const subject = new FlowSubject(reducer);
 * subject.subscribe((state) => console.log(state.count));
 * subject.next({ type: 'increment' }); // logs: 1
 * ```
 */
export declare class FlowSubject<S, A extends Action = Action> extends Observable<S> {
    #private;
    /**
     * Observable stream of actions dispatched to the subject.
     */
    get action$(): Observable<A>;
    /**
     * The current value of state.
     */
    get value(): S;
    /**
     * Flag to indicate if the observable is closed.
     */
    get closed(): boolean;
    /**
     * Creates a new instance of the FlowSubject class with an initial state reducer.
     * @param reducer A reducer with an initial state or a reducer function.
     */
    constructor(reducer: ReducerWithInitialState<S, A>);
    /**
     * Create a new instance of the FlowSubject class with a reducer function and initial state.
     * @param reducer state reducer
     * @param initialState initial state
     */
    constructor(reducer: Reducer<S, A>, initialState: S);
    /**
     * Resets the state to the initial value.
     */
    reset: VoidFunction;
    /**
     * Dispatches an action to the subject.
     *
     * @param action The action to dispatch.
     */
    next(action: A): void;
    /**
     * Selects a derived state from the observable state and emits only when the selected state changes.
     *
     * @param selector - A function that takes the current state and returns a derived state.
     * @param comparator - An optional function that compares the previous and current derived states to determine if a change has occurred.
     * @returns An observable that emits the derived state whenever it changes.
     */
    select<T>(selector: (state: S) => T, comparator?: (previous: T, current: T) => boolean): Observable<T>;
    /**
     * Adds an effect that listens for actions and performs side effects.
     *
     * @param fn The effect function to execute.
     * @returns A subscription to the effect.
     */
    addEffect(fn: Effect<A, S>): Subscription;
    /**
     * Adds an effect that listens for a specific action type and performs side effects.
     *
     * @param actionType The type of action to listen for.
     * @param cb The effect function to execute when the action is dispatched.
     * @returns A subscription to the effect.
     */
    addEffect<TType extends ActionType<A>>(actionType: TType, cb: Effect<ExtractAction<A, NoInfer<TType>>, S>): Subscription;
    /**
     * Adds an effect that listens for an array of action types and performs side effects.
     *
     * @param actionType The array of action types to listen for.
     * @param cb The effect function to execute when one of the actions is dispatched.
     * @returns A subscription to the effect.
     */
    addEffect<TType extends ActionType<A>>(actionType: Array<TType>, cb: Effect<ExtractAction<A, NoInfer<TType>>, S>): Subscription;
    /**
     * @deprecated Use {@link FlowSubject.addFlow} instead.
     *
     * @param fn - The flow function to execute.
     * @returns A subscription to the flow.
     */
    addEpic(fn: Flow<A, S>): Subscription;
    /**
     * Adds a flow (epic-style) that transforms the action stream and optionally
     * reads state, then emits new actions back into the subject.
     *
     * Flows receive the full `action$` stream and the state observable, and must
     * return an `Observable<A>`. This is useful for complex async orchestration.
     *
     * @param fn - The flow function that receives `(action$, state$)` and returns an action observable.
     * @returns A subscription to the flow. Unsubscribe to remove the flow.
     * @throws {TypeError} If the flow function does not return an observable.
     *
     * @example
     * ```ts
     * subject.addFlow((action$) =>
     *   action$.pipe(
     *     filterAction('fetchData'),
     *     switchMap((action) =>
     *       fetchApi(action.payload).pipe(
     *         map((data) => ({ type: 'fetchSuccess', payload: data })),
     *       ),
     *     ),
     *   ),
     * );
     * ```
     */
    addFlow(fn: Flow<A, S>): Subscription;
    /**
     * Tears down the subject by unsubscribing both the action and state subjects.
     *
     * After calling this method, the subject is no longer usable.
     */
    unsubscribe(): void;
    /**
     * Completes both the action and state subjects, signalling to all
     * subscribers that no further values will be emitted.
     */
    complete(): void;
    /**
     * Returns a plain `Observable` of the state, hiding the subject's
     * `next`, `complete`, and other mutation methods.
     *
     * @returns A read-only observable of the state.
     */
    asObservable(): Observable<S>;
}
export default FlowSubject;
