import { AbstractStore } from './AbstractStore';
import { StoreConfig } from './models/StoreConfig';
import { Predicate, Delta } from './models/';
import { Observable } from 'rxjs';
import { Slice } from './Slice';
/**
 * This `todoFactory` code will be used to illustrate the API examples.  The following
 * utilities are used in the tests and the API Typedoc examples contained here.
 * @example Utilities for API Examples
 * ```
 * export const enum TodoSliceEnum {
 *    COMPLETE = "Complete",
 *    INCOMPLETE = "Incomplete"
 * }
 * export class Todo {
 *    constructor(
 *         public complete: boolean,
 *         public title: string,
 *         public gid?:string,
 *         public id?:string) {}
 * }
 *
 * export let todos = [new Todo(false, "You complete me!"), new Todo(true, "You completed me!")];
 *
 * export function todosFactory():Todo[] {
 *   return [new Todo(false, "You complete me!"), new Todo(true, "You completed me!")];
 * }
 * ```
 */
export declare class EStore<E> extends AbstractStore<E> {
    /**
     * Store constructor (Initialization with element is optional)
     *
     * perform initial notification to all observers,
     * such that functions like {@link combineLatest}{}
     * will execute at least once.
     *
     * @param entities The entities to initialize the store with.
     * @param config The optional configuration instance.
     *
     * @example EStore<Todo> Creation
     * ```
     * // Initialize the Store
     * let store: EStore<Todo> = new EStore<Todo>(todosFactory());
     * ```
     */
    constructor(entities?: E[], config?: StoreConfig);
    /**
     * Calls complete on all EStore {@link ReplaySubject} instances.
     *
     * Call destroy when disposing of the store.
     */
    destroy(): void;
    /**
     * Toggles the entity:
     *
     * If the store contains the entity
     * it will be deleted.  If the store
     * does not contains the entity,
     * it is added.
     * @param e The entity to toggle
     * @example Toggle the Todo instance
     * ```
     * estore.post(todo);
     * // Remove todo
     * estore.toggle(todo);
     * // Add it back
     * estore.toggle(todo);
     * ```
     */
    toggle(e: E): void;
    /**
     * Notifies observers when the store is empty.
     */
    private notifyActive;
    /**
     * `Map` of active entties. The instance is public and can be used
     * directly to add and remove active entities, however we recommend
     * using the {@link addActive} and {@link deleteActive} methods.
     */
    active: Map<string, E>;
    /**
     * Add multiple entity entities to active.
     *
     * If the entity is not contained in the store it is added
     * to the store before it is added to `active`.
     *
     * Also we clone the map prior to broadcasting it with
     * `notifyActive` to make sure we will trigger Angular
     * change detection in the event that it maintains
     * a reference to the `active` state `Map` instance.
     *
     * @example Add todo1 and todo2 as active
     * ```
     * addActive(todo1);
     * addActive(todo2);
     * ```
     */
    addActive(e: E): void;
    /**
     * Delete an active entity.
     *
     * Also we clone the map prior to broadcasting it with
     * `notifyActive` to make sure we will trigger Angular
     * change detection in the event that it maintains
     * a reference to the `active` state `Map` instance.
     *
     * @example Remove todo1 and todo2 as active entities
     * ```
     * deleteActive(todo1);
     * deleteActive(todo2);
     * ```
     */
    deleteActive(e: E): void;
    /**
     * Clear / reset the active entity map.
     *
     * Also we clone the map prior to broadcasting it with
     * `notifyActive` to make sure we will trigger Angular
     * change detection in the event that it maintains
     * a reference to the `active` state `Map` instance.
     *
     * @example Clear active todo instances
     * ```
     * store.clearActive();
     * ```
     */
    clearActive(): void;
    /**
     * Observe the active entities.
     *
     * @example
     * ```
     * let active$ = store.observeActive();
     * ```
     */
    observeActive(): Observable<Map<string, E>>;
    /**
     * Observe the active entity.
     * @example
       <pre>
      let active$ = source.activeSnapshot();
      </pre>
    */
    activeSnapshot(): E[];
    /**
     * Observable of errors occurred during a load request.
     *
     * The error Observable should be created by the
     * client.
     */
    loadingError: Observable<any>;
    /**
     * Notifies observers when the store is loading.
     *
     * This is a common pattern found when implementing
     * `Observable` data sources.
     */
    private notifyLoading;
    /**
     * The current loading state.  Use loading when fetching new
     * data for the store.  The default loading state is `true`.
     *
     * This is such that if data is fetched asynchronously
     * in a service, components can wait on loading notification
     * before attempting to retrieve data from the service.
     *
     * Loading could be based on a composite response.  For example
     * when the stock and mutual funds have loaded, set loading to `false`.
     */
    private _loading;
    /**
     * Sets the current loading state and notifies observers.
     */
    set loading(loading: boolean);
    /**
     * @return A snapshot of the loading state.
     * @example Create a reference to the loading state
     * ```
     * const loading:boolean = todoStore.loading;
     * ```
     */
    get loading(): boolean;
    /**
     * Observe loading.
     *
     * Note that this obverable piped through
     * `takeWhile(v->v, true), such that it will
     * complete after each emission.
     *
     * See:
     * https://fireflysemantics.medium.com/waiting-on-estore-to-load-8dcbe161613c
     *
     * For more details.
     * Also note that v=>v is the same as v=>v!=false
     *
     * @example
     * ```
     * const observeLoadingHandler: Observer<boolean> = {
     *   complete: () => {
     *     console.log(`Data Loaded and Observable Marked as Complete`);
     *   }, // completeHandler
     *   error: () => {
     *     console.log(`Any Errors?`);
     *   }, // errorHandler
     *   next: (l) => {
     *     console.log(`Data loaded and loading is ${l}`);
     *   },
     * };
     *
     * const observeLoadingResubscribeHandler: Observer<boolean> = {
     *   complete: () => {
     *     console.log(`Data Loaded and Resubscribe Observable Marked as Complete`);
     *   }, // completeHandler
     *   error: () => {
     *     console.log(`Any Resubscribe Errors?`);
     *   }, // errorHandler
     *   next: (l) => {
     *     console.log(`Data loaded and resusbscribe loading  value is ${l}`);
     *   },
     * };
     *
     * const todoStore: EStore<Todo> = new EStore();
     * //============================================
     * // Loading is true by default
     * //============================================
     * console.log(`The initial value of loading is ${todoStore.loading}`);
     * //============================================
     * // Observe Loading
     * //============================================
     * let loading$: Observable<boolean> = todoStore.observeLoading();
     * loading$.subscribe((l) => console.log(`The value of loading is ${l}`));
     *
     * todoStore.loading = false;
     * loading$.subscribe(observeLoadingHandler);
     * //============================================
     * // The subscription no longer fires
     * //============================================
     * todoStore.loading = true;
     * todoStore.loading = false;
     *
     * //============================================
     * // The subscription no longer fires,
     * // so if we want to observe loading again
     * // resusbscribe.
     * //============================================
     * todoStore.loading = true;
     * loading$ = todoStore.observeLoading();
     * loading$.subscribe(observeLoadingResubscribeHandler);
     * todoStore.loading = false;
     * ```
     */
    observeLoading(): Observable<boolean>;
    /**
     * Notfiies when loading has completed.
     */
    observeLoadingComplete(): Observable<boolean>;
    /**
     * Observable of errors occurred during a search request.
     *
     * The error Observable should be created by the
     * client.
     */
    searchError: Observable<any>;
    /**
     * Notifies observers that a search is in progress.
     *
     * This is a common pattern found when implementing
     * `Observable` data sources.
     */
    private notifySearching;
    /**
     * The current `searching` state.  Use `searching`
     * for example to display a spinnner
     * when performing a search.
     * The default `searching` state is `false`.
     */
    private _searching;
    /**
     * Sets the current searching state and notifies observers.
     */
    set searching(searching: boolean);
    /**
     * @return A snapshot of the searching state.
     */
    get searching(): boolean;
    /**
     * Observe searching.
     * @example
       <pre>
      let searching$ = source.observeSearching();
      </pre>
    
      Note that this obverable piped through
      `takeWhile(v->v, true), such that it will
      complete after each emission.
    
      See:
      https://medium.com/@ole.ersoy/waiting-on-estore-to-load-8dcbe161613c
    
      For more details.
    */
    observeSearching(): Observable<boolean>;
    /**
     * Notfiies when searching has completed.
     */
    observeSearchingComplete(): Observable<boolean>;
    /**
     * Store slices
     */
    private slices;
    /**
     * Adds a slice to the store and keys it by the slices label.
     *
     * @param p
     * @param label
     *
     * @example Setup a Todo Slice for COMPLETE Todos
  ```
  source.addSlice(todo => todo.complete, TodoSlices.COMPLETE);
  ```
     */
    addSlice(p: Predicate<E>, label: string): void;
    /**
     * Remove a slice
     * @param label The label identifying the slice
     *
     * @example Remove the TodoSlices.COMPLETE Slice
  ```
  source.removeSlice(TodoSlices.COMPLETE);
  ```
     */
    removeSlice(label: string): void;
    /**
     * Get a slice
     * @param label The label identifying the slice
     * @return The Slice instance or undefined
     *
     * @example Get the TodoSlices.COMPLETE slice
  ```
  source.getSlice(TodoSlices.COMPLETE);
  ```
     */
    getSlice(label: string): Slice<E> | undefined;
    /**
     * Post (Add a new) element(s) to the store.
     * @param e An indiidual entity or an array of entities
     * @example Post a Todo instance.
     *
     *```
     * store.post(todo);
     *```
     */
    post(e: E | E[]): void;
    /**
     * Post N entities to the store.
     * @param ...e
     * @example Post two Todo instances.
     * ```
     * store.post(todo1, todo2);
     * ```
     */
    postN(...e: E[]): void;
    /**
     * Post (Add) an array of elements to the store.
     * @param e
     * @example Post a Todo array.
     *
     * ```
     * store.post([todo1, todo2]);
     * ```
     */
    postA(e: E[]): void;
    /**
     * Put (Update) an entity.
     * @param e
     * @example Put a Todo instance.
     * ```
     * store.put(todo1);
     * ```
     */
    put(e: E | E[]): void;
    /**
     * Put (Update) an element or add an element that was read from a persistence source
     * and thus already has an assigned global id`.
     * @param e The enetity instances to update.
     * @example Put N Todo instances.
     *
     * ```
     * store.put(todo1, todo2);
     * ```
     */
    putN(...e: E[]): void;
    /**
     * Put (Update) the array of enntities.
     * @param e The array of enntities to update
     * @example Put an array of Todo instances.
     * ```
     * store.put([todo1, todo2]);
     * ```
     */
    putA(e: E[]): void;
    /**
     * Delete (Update) the array of elements.
     * @param e
     * @example Delete todo1.
     * ```
     * store.delete(todo1]);
     * ```
     */
    delete(e: E | E[]): void;
    /**
     * Delete N elements.
     * @param ...e
     * @example Delete N Todo instance argument.
     * ```
     * store.deleteN(todo1, todo2);
     * ```
     */
    deleteN(...e: E[]): void;
    /**
     * Delete an array of elements.
     * @param e The array of instances to be deleted
     * @example Delete the array of Todo instances.
     * ```
     * store.deleteA([todo1, todo2]);
     * ```
     */
    deleteA(e: E[]): void;
    /**
     * Delete elements by {@link Predicate}.
     * @param p The predicate.
     * @example Delete the Todo instances.
     * ```
     * store.delete(todo1, todo2);
     * ```
     */
    deleteP(p: Predicate<E>): void;
    /**
     * If the entity has the `id` key initialized with a value,
     * then also add the entity to the `idEntries`.
     *
     * @param e The element to be added to the `idEntries`.
     */
    private updateIDEntry;
    /**
     * If the entity has the `id` key initialized with a value,
     * then also delete the entity to the `idEntries`.
     *
     * @param e The element to be added to the `idEntries`.
     */
    private deleteIDEntry;
    /**
     * Resets the store and all contained slice instances to empty.
     * Also perform delta notification that sends all current store entries.
     * The ActionType.RESET code is sent with the delta notification.  Slices
     * send their own delta notification.
     *
     * @example Reset the store.
     * ```
     * store.reset();
     * ```
     */
    reset(): void;
    /**
     * Call all the notifiers at once.
     *
     * @param v
     * @param delta
     */
    protected notifyAll(v: E[], delta: Delta<E>): void;
}
