import { Observable, Observer } from 'rxjs';

/**
 * Returns a value provided by `source$`.
 *
 * The hook returns the initial value and subscribes on the `source$`. After
 * that, the hook returns values which are provided by the source.
 *
 * @param source$ an observable for values
 * @param initialValue th first value which is returned by the hook
 * @param comparator a comparator for previous and next values
 *
 * @example
 * ```ts
 * const value = useObservable<string>(source$, undefined);
 * ```
 */
declare function useObservable<T>(source$: Observable<T>, initialValue: T, comparator?: (v1: T, v2: T) => boolean): T;

/**
 * Subscribes the provided observer or `next` handler on `source$` observable.
 *
 * This hook allows to do fine handling of the source observable.
 *
 * @param source$ an observable
 * @param observerOrNext `Observer` or `next` handler
 *
 * @example
 * ```ts
 * useObserver(source$, (nextValue) => {
 *   logger.log(nextValue);
 * });
 * ```
 */
declare function useObserver<T>(source$: Observable<T>, observerOrNext: Partial<Observer<T>> | ((value: T) => void)): void;

/**
 * Returns a value provided by `source$`.
 *
 * The hook returns the initial value and subscribes on the `source$`. After
 * that, the hook returns values which are provided by the source.
 *
 * @param source$ an observable for values
 * @param initialValue th first value which is returned by the hook
 * @param selector a transform function for getting a derived value based on
 *   the source value
 * @param comparator a comparator for previous and next values
 *
 * @example
 * ```ts
 * const value = useSelector<{data: Record<string, string>}>(
 *   source$,
 *   undefined,
 *   (state) => state.data,
 *   (data1, data2) => data1.key === data2.key
 * );
 * ```
 */
declare function useSelector<S, R>(source$: Observable<S>, initialValue: S, selector: (state: S) => R, comparator?: (v1: R, v2: R) => boolean): R;

export { useObservable, useObserver, useSelector };
