import { StateCreator, StoreApi, StoreMutatorIdentifier } from "zustand";

//#region src/computed.d.ts
/**
 * Options for when and how your compute function is called.
 */
type ComputedStateOpts<T> = ({
  /**
   * An explicit list of keys to track for recomputation. By default,
   * `zustand-computed` will run your compute function on any change.
   * This lets you filter those keys out. It's better to use the
   * `compareFn` to be more explicit about how comparison is determined.
   */
  keys?: (keyof T)[];
} | {
  /**
   * Custom comparison function to determine whether to recompute.
   * Receives the previous and next store state, should return true if
   * compute should run, false to skip recomputation. This function
   * should be *fast* - it determines whether or not you need to
   * recompute.
   */
  shouldRecompute?: (state: T, nextState: T | Partial<T>) => boolean;
}) & {
  /**
   * @deprecated removed proxy; this does nothing and will be removed.
   */
  disableProxy?: boolean;
  /**
   * Custom equality function for comparing computed values. By default, we use
   * `zustand/shallow` to compare each key in your store against the newly-
   * computed values. This is likely the desired method of comparison.
   *
   * The motivation for this function is to ensure that, in the case your
   * computed function returns a value that is identical structurally, it
   * should not cause a re-render despite the reference being different.
   *
   * You can disable comparison, so that the most recent result of the
   * compute function always triggers downstream re-renders, by simply
   * returning false.
   */
  equalityFn?: <Y>(a: Y, b: Y) => boolean;
};
type ComputedStateCreator = <T extends object, A extends object>(compute: (state: T) => A, opts?: ComputedStateOpts<T>) => <Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = [], U = T>(f: StateCreator<T, [...Mps, ["chrisvander/zustand-computed", A]], Mcs>) => StateCreator<T, Mps, [["chrisvander/zustand-computed", A], ...Mcs], U & A>;
type Cast<T, U> = T extends U ? T : U;
type Write<T, U> = Omit<T, keyof U> & U;
type StoreCompute<S, A> = S extends {
  getState: () => infer T;
} ? Pick<StoreApi<T & A>, "getState" | "getInitialState"> : never;
type WithCompute<S, A> = Write<S, StoreCompute<S, A>>;
declare module "zustand/vanilla" {
  interface StoreMutators<S, A> {
    "chrisvander/zustand-computed": WithCompute<Cast<S, object>, A>;
  }
}
declare const createComputed: ComputedStateCreator;
//#endregion
export { ComputedStateCreator, ComputedStateOpts, createComputed };