import { IDisposable, BatchDisposable, IBatchDisposable } from '@guanghechen/disposable';
export * from '@guanghechen/disposable';
import { IBaseObservable, IValueList, IObservableOptions, IEquals, IObservable, IObservableNextOptions, Observable, IObservableKey } from '@guanghechen/observable';
export * from '@guanghechen/observable';
import { ISubscriber, IUnsubscribable, ISubscribable } from '@guanghechen/subscriber';
export * from '@guanghechen/subscriber';

interface IComputed<T> extends IBaseObservable<T> {
    getServerSnapshot?: () => T;
    subscribeStateChange: (onStoreChange: () => void) => () => void;
}

declare class Computed<T> implements IComputed<T> {
    protected readonly _observable: IBaseObservable<T>;
    constructor(observable: IBaseObservable<T>);
    static fromObservables<S extends Array<IBaseObservable<any>>, T>(observables: S, transform: (values: IValueList<S>) => T, options?: IObservableOptions<T>): Computed<T>;
    get disposed(): boolean;
    dispose(): void;
    registerDisposable<T extends IDisposable>(disposable: T): void;
    subscribe(subscriber: ISubscriber<T>): IUnsubscribable;
    readonly getSnapshot: () => T;
    readonly getServerSnapshot: () => T;
    readonly subscribeStateChange: (onStateChange: () => void) => (() => void);
}

interface IImmutableCollection<K, V> {
    has(key: K): boolean;
    get(key: K): V | undefined;
    keys(): Iterable<K>;
    values(): Iterable<V>;
    entries(): Iterable<[K, V]>;
    withMutations(mutator: (mutable: this) => void): this;
}
interface IImmutableMap<K, V> extends IImmutableCollection<K, V> {
    set(key: K, value: V): this;
    delete(key: K): this;
    deleteAll(keys: Iterable<K>): this;
    merge(entries: Iterable<[K, V]>): this;
}
interface IImmutableSet<V> extends IImmutableCollection<V, V> {
    add(value: V): this;
    delete(key: V): this;
}

interface IObservableCollectionOptions<V> {
    valueEquals?: IEquals<V | undefined>;
}
interface IObservableCollection<K, V, C extends IImmutableCollection<K, V>> extends IObservable<C> {
    has(key: K): boolean;
    get(key: K): V | undefined;
    keys(): Iterable<K>;
    values(): Iterable<V>;
    entries(): Iterable<[K, V]>;
    observeKey(key: K): IObservable<V | undefined>;
    subscribeKey(key: K, subscriber: ISubscriber<V | undefined>): IUnsubscribable;
}
interface IObservableMap<K, V, C extends IImmutableMap<K, V>> extends IObservableCollection<K, V, C> {
    set(key: K, value: V, options?: IObservableNextOptions): void;
    delete(key: K, options?: IObservableNextOptions): void;
    deleteAll(keys: Iterable<K>, options?: IObservableNextOptions): void;
    merge(entries: Iterable<[K, V]>, options?: IObservableNextOptions): void;
}
interface IObservableSet<V, C extends IImmutableSet<V>> extends IObservableCollection<V, V, C> {
    add(value: V, options?: IObservableNextOptions): void;
    addAll(values: Iterable<V>, options?: IObservableNextOptions): void;
    delete(value: V, options?: IObservableNextOptions): void;
    deleteAll(values: Iterable<V>, options?: IObservableNextOptions): void;
}

interface IObservableSubscriber<T> {
    readonly subscriber: ISubscriber<T>;
    inactive: boolean;
}
declare class ObservableCollection<K, V, C extends IImmutableCollection<K, V>> extends BatchDisposable implements IObservableCollection<K, V, C> {
    readonly equals: IEquals<C>;
    readonly valueEquals: IEquals<V | undefined>;
    protected readonly _subscribers: Array<IObservableSubscriber<C>>;
    protected readonly _keySubscribersMap: Map<K, Array<IObservableSubscriber<V | undefined>>>;
    protected _value: C;
    protected _lastNotifiedValue: C | undefined;
    constructor(defaultValue: C, options?: IObservableCollectionOptions<V>);
    dispose(): void;
    has(key: K): boolean;
    get(key: K): V | undefined;
    keys(): Iterable<K>;
    values(): Iterable<V>;
    entries(): Iterable<[K, V]>;
    getSnapshot(): C;
    next(value: C, options?: IObservableNextOptions): void;
    subscribe(subscriber: ISubscriber<C>): IUnsubscribable;
    observeKey(key: K): IObservable<V | undefined>;
    subscribeKey(key: K, subscriber: ISubscriber<V | undefined>): IUnsubscribable;
    protected _notify(): void;
}

declare class DisposedObservable<T> implements IObservable<T> {
    readonly equals: IEquals<T>;
    protected _value: T;
    constructor(defaultValue: T, options?: IObservableOptions<T>);
    get disposed(): boolean;
    dispose(): void;
    registerDisposable<T extends IDisposable>(disposable: T): void;
    getSnapshot(): T;
    next(value: T, options?: IObservableNextOptions): void;
    subscribe(subscriber: ISubscriber<T>): IUnsubscribable;
}

declare class ObservableMap<K, V, C extends IImmutableMap<K, V>> extends ObservableCollection<K, V, C> implements IObservableMap<K, V, C> {
    set(key: K, value: V, options?: IObservableNextOptions): void;
    delete(key: K, options?: IObservableNextOptions): void;
    deleteAll(keys: Iterable<K>, options?: IObservableNextOptions): void;
    merge(entries: Iterable<[K, V]>, options?: IObservableNextOptions): void;
}

declare class ObservableSet<V, C extends IImmutableSet<V>> extends ObservableCollection<V, V, C> implements IObservableSet<V, C> {
    add(value: V, options?: IObservableNextOptions): void;
    addAll(values: Iterable<V>, options?: IObservableNextOptions): void;
    delete(value: V, options?: IObservableNextOptions): void;
    deleteAll(values: Iterable<V>, options?: IObservableNextOptions): void;
}

type IValuePatcher<T> = (prev: T) => T;
interface IState<T> extends IComputed<T> {
    /**
     *
     * @param nextValue
     */
    next(nextValue: T): void;
    /**
     *
     * @param patch
     */
    setState(patch: IValuePatcher<T>): void;
    /**
     *
     * @param patch
     */
    updateState(patch: T | IValuePatcher<T>): void;
}

declare class State<T> extends Observable<T> implements IState<T> {
    readonly getSnapshot: () => T;
    readonly getServerSnapshot: () => T;
    readonly setState: (patch: IValuePatcher<T>) => void;
    readonly updateState: (patch: T | IValuePatcher<T>) => void;
    readonly subscribeStateChange: (onStateChange: () => void) => (() => void);
}

interface IViewModelTicker {
    readonly keys: ReadonlyArray<string>;
    readonly ticker: ISubscribable<number> & IDisposable;
}
interface IViewModel extends IBatchDisposable {
    /**
     * Create a tick observable to watch changes in keys of this.
     * @param keys
     */
    ticker<K extends IObservableKey<this>>(keys: K[] | undefined): Readonly<IViewModelTicker>;
}

declare abstract class ViewModel extends BatchDisposable implements IViewModel {
    protected readonly _tickerMap: Map<string, IViewModelTicker>;
    constructor();
    dispose(): void;
    ticker<K extends IObservableKey<this>>(observableKeys: K[]): Readonly<IViewModelTicker>;
}

export { Computed, DisposedObservable, type IComputed, type IImmutableCollection, type IImmutableMap, type IImmutableSet, type IObservableCollection, type IObservableCollectionOptions, type IObservableMap, type IObservableSet, type IState, type IValuePatcher, type IViewModel, type IViewModelTicker, ObservableCollection, ObservableMap, ObservableSet, State, ViewModel };
