import { Observable, Subscription } from 'rxjs';
import { ColdObservable as ColdObservable$1 } from 'rxjs/internal/testing/ColdObservable';
import { TestScheduler } from 'rxjs/testing';
import { HotObservable as HotObservable$1 } from 'rxjs/internal/testing/HotObservable';

/**
 * Exported return type of TestMessage[] to avoid importing internal APIs.
 */
type TestMessages = ReturnType<typeof TestScheduler.parseMarbles>;
/**
 * Exported return type of SubscriptionLog to avoid importing internal APIs.
 */
type SubscriptionLog = ReturnType<typeof TestScheduler.parseMarblesAsSubscriptions>;

declare class ColdObservable<T = unknown> extends Observable<T> {
    marbles: string;
    values?: Record<string, T> | undefined;
    error?: any | undefined;
    source: ColdObservable$1<T>;
    constructor(marbles: string, values?: Record<string, T> | undefined, error?: any | undefined);
    getSubscriptions(): SubscriptionLog[];
}

declare class HotObservable<T = unknown> extends Observable<T> {
    marbles: string;
    values?: Record<string, T> | undefined;
    error?: any | undefined;
    source: HotObservable$1<T>;
    constructor(marbles: string, values?: Record<string, T> | undefined, error?: any | undefined);
    getSubscriptions(): SubscriptionLog[];
}

declare class Scheduler {
    static instance: TestScheduler | null;
    private static onFlush;
    private static currentAnimate;
    private static prevFrameTimeFactor;
    static init(): void;
    static get(): TestScheduler;
    static reset(): void;
    private static flushTests;
    static captureAnimate(animate: (marbles: string) => void): void;
    static animate(marbles: string): void;
    static markLastNegated(): void;
    static markLastReady(): void;
    static queueOnFlush(fn: () => void): void;
    static clearFlushTests(): void;
    static installNegationAwareAssert(): void;
    static teardown(): void;
    static materializeInnerObservable(observable: Observable<any>, outerFrame: number): TestMessages;
}

declare function marbleTest(fn: () => void): () => void;

declare function animate(marbles: string): void;

type ObservableWithSubscriptions = ColdObservable<any> | HotObservable<any>;

declare global {
    namespace jest {
        interface Matchers<R extends void | Promise<void>> {
            toBeObservable(observable: ObservableWithSubscriptions): R;
            toHaveSubscriptions(marbles: string | string[]): R;
            toHaveNoSubscriptions(): R;
            toBeMarble(marble: string): R;
            toSatisfyOnFlush(func: () => void): R;
        }
    }
}
declare module 'expect' {
    interface Matchers<R extends void | Promise<void>> {
        toBeObservable(observable: ObservableWithSubscriptions): R;
        toHaveSubscriptions(marbles: string | string[]): R;
        toHaveNoSubscriptions(): R;
        toBeMarble(marble: string): R;
        toSatisfyOnFlush(func: () => void): R;
    }
}
declare function hot<T = unknown>(marbles: string, values?: Record<string, T>, error?: any): HotObservable<T>;
declare function cold<T = unknown>(marbles: string, values?: Record<string, T>, error?: any): ColdObservable<T>;
declare function time(marbles: string): number;
declare function schedule(work: () => void, delay: number): Subscription;

export { type ObservableWithSubscriptions, Scheduler, animate, cold, hot, marbleTest, schedule, time };
