import * as svelte_store from 'svelte/store';
import { StartStopNotifier, Readable, Writable, Updater } from 'svelte/store';

declare function readable<T>(value?: T, start?: StartStopNotifier<T>): Readable<T>;

/**
 * Any function
 */
declare type Fn = (...args: any[]) => void;
/**
 * Any promise function
 */
declare type PromiseFn<T> = (...args: any[]) => Promise<T>;
/**
 * Infers the element type of an array
 */
declare type ElementOf<T> = T extends (infer E)[] ? E : never;
/**
 * Maybe it's a Readable, or not.
 *
 * ```ts
 * type Readable = T | Readable<T>
 * ```
 */
declare type MaybeReadable<T> = T | Readable<T>;
/**
 * Maybe it's a Writable, or not.
 *
 * ```ts
 * type Writable = T | Writable<T>
 * ```
 */
declare type MaybeWritable<T> = T | Writable<T>;
declare type MaybeElementReadable = MaybeReadable<HTMLElement | SVGElement | undefined | null>;
/**
 * A writable that allow to set/update `null` or `undefined`
 */
declare type RemovableWritable<T> = Writable<T> & {
    set(this: void, value: T | null | undefined): void;
    update(this: void, updater: Updater<T | null | undefined>): void;
};
interface Stopable {
    /**
     * A writable indicate whether a stopable instance is executing
     */
    isPending: Writable<boolean>;
    /**
     * Stop the effect from executing
     */
    stop: Fn;
    /**
     * Start the effect
     */
    start: Fn;
}
interface Pausable {
    /**
     * A readable indicate whether a pausable instance is active
     */
    isActive: Writable<boolean>;
    /**
     * Temporary pause the effect from executing
     */
    pause: Fn;
    /**
     * Resume the efffects
     */
    resume: Fn;
}

declare const isClient: boolean;
declare const isDef: <T = any>(val?: T | undefined) => val is T;
declare const assert: (condition: boolean, ...infos: any[]) => void;
declare const isBoolean: (val: any) => val is boolean;
declare const isFunction: <T extends Function>(val: any) => val is T;
declare const isNumber: (val: any) => val is number;
declare const isString: (val: unknown) => val is string;
declare const isObject: (val: any) => val is object;
declare const isWindow: (val: any) => val is Window;
declare const isReadable: <T>(store: any) => store is Readable<T>;
declare const isWritable: <T>(store: any) => store is Writable<T>;
declare const now: () => number;
declare const timestamp: () => number;
declare const clamp: (n: number, min: number, max: number) => number;
declare const noop: () => void;
declare const rand: (min: number, max: number) => number;

/**
 *  Run a function
 */
declare const run: (fn: Fn, ...args: any[]) => void;
/**
 * Run all functions
 */
declare const runAll: (fns: Fn[], ...args: any[]) => void;

/**
 * Silent `get_current_component`. Call `get_current_component()` without throw error.
 */
declare function tryGetCurrentComponent(): any;
declare function promiseTimeout(ms: number, throwOnTimeout?: boolean, reason?: string): Promise<void>;
declare function unstore<T>(val: MaybeReadable<T>): T;
declare function toReadable<T>(val: MaybeReadable<T> | MaybeWritable<T>): Readable<T>;
declare function toWritable<T>(val: MaybeWritable<T>): Writable<T>;

/**
 * Call onDestroy() if it's inside a component lifecycle, if not, do nothing.
 *
 * @param fn
 */
declare function tryOnDestroy(fn: Fn): void;

/**
 * Call `onMount()` if it's inside a component lifecycle, if not, run just call the function.
 *
 * @param fn
 */
declare function tryOnMount(fn: Fn | (() => Fn)): void;

interface IntervalOptions<Controls extends boolean> {
    /**
     * Expose the controls
     *
     * @default false
     */
    controls?: Controls;
    /**
     * Execute the update immediately on calling
     *
     * @default true
     */
    immediate?: boolean;
}
declare function useInterval(interval?: number, options?: IntervalOptions<false>): Writable<number>;
declare function useInterval(interval: number, options: IntervalOptions<true>): {
    counter: Writable<number>;
} & Pausable;

interface IntervalFnOptions {
    /**
     * Start the timer immediately
     *
     * @default true
     */
    immediate?: boolean;
    /**
     * Execute the callback immediate after calling this function
     *
     * @default false
     */
    immediateCallback?: boolean;
}
/**
 * Wrapper for `setInterval` with controls
 *
 * @param cb
 * @param interval
 * @param options
 */
declare function useIntervalFn(cb: Fn, interval?: number, options?: IntervalFnOptions): Pausable;

interface TimeoutFnOptions {
    /**
     * Start the timer immediate after calling this function
     *
     * @default true
     */
    immediate?: boolean;
}
/**
 * Wrapper for `setTimeout` with controls.
 *
 * @param fn
 * @param interval
 * @param options
 */
declare function useTimeoutFn(cb: (...args: unknown[]) => any, interval: number, options?: TimeoutFnOptions): Stopable;

interface TimeoutOptions<Controls extends boolean> extends TimeoutFnOptions {
    /**
     * Expose more controls
     *
     * @default false
     */
    controls?: Controls;
}
/**
 * Update value after a given time with controls.
 *
 * @see https://svelte-use.vercel.app/core/useTimeout
 * @param interval
 * @param options
 */
declare function useTimeout(interval?: number, options?: TimeoutOptions<false>): Writable<boolean>;
declare function useTimeout(interval: number, options: TimeoutOptions<true>): {
    ready: Writable<boolean>;
} & Stopable;

/**
 * Shorthand for watching value to be truthy
 *
 * @see https://svelte-use.vercel.app/shared/whenever
 */
declare function whenever<T>(source: MaybeWritable<T>, cb: Fn): svelte_store.Unsubscriber;

declare function writable<T>(value?: T, start?: StartStopNotifier<T>): Writable<T>;

export { ElementOf, Fn, IntervalFnOptions, IntervalOptions, MaybeElementReadable, MaybeReadable, MaybeWritable, Pausable, PromiseFn, RemovableWritable, Stopable, TimeoutFnOptions, TimeoutOptions, assert, clamp, isBoolean, isClient, isDef, isFunction, isNumber, isObject, isReadable, isString, isWindow, isWritable, noop, now, promiseTimeout, rand, readable, run, runAll, timestamp, toReadable, toWritable, tryGetCurrentComponent, tryOnDestroy, tryOnMount, unstore, useInterval, useIntervalFn, useTimeout, useTimeoutFn, whenever, writable };
