import type {ClientPerspective} from '@sanity/client'
import {ComponentType} from 'react'
import {LazyExoticComponent} from 'react'
import type {QueryParams} from '@sanity/client'
import type {SanityClient} from '@sanity/client'

/**
 * @public
 * @deprecated these options are no longer used
 */
export declare interface CacheOptions {
  /**
   * Uses a `Listen` API call with EventSource to stream updates in real-time to the documents cache
   * @defaultValue true
   */
  listen?: boolean
  /**
   * The maximum number of documents to keep in the in-memory
   * @defaultValue 3000
   */
  maxDocuments?: number
  /**
   * Set it to an array over document `_type` names to filter the cache to, set it to an empty array to cache any type
   * @defaultValue []
   */
  includeTypes?: string[]
}

/**
 * @internal
 */
export declare type DefineListenerContext = <QueryResult>(
  initialSnapshot: QueryResult,
  query: string,
  params: QueryParams,
) => {
  subscribe: ListenerSubscribe
  getSnapshot: ListenerGetSnapshot<QueryResult>
}

/**
 * By default 'react-fast-compare' is used to check if the query result has changed.
 * It's reasonably fast, but you can make it even faster by providing your own function as you know which
 * part of the query result is visible to the user, and which parts can skip rendering.
 * @public
 */
export declare type isEqualFn<QueryResult> = (a: QueryResult, b: QueryResult) => boolean

/**
 * @internal
 */
export declare type ListenerGetSnapshot<QueryResult> = () => QueryResult

/**
 * @internal
 */
export declare type ListenerSubscribe = (onStoreChange: () => void) => () => void

/** @public */
export declare interface LiveQueryHookOptions<QueryResult> {
  isEqual?: isEqualFn<QueryResult>
}

/** @public */
declare const LiveQueryProvider: LazyExoticComponent<ComponentType<LiveQueryProviderProps>>
export {LiveQueryProvider}
export default LiveQueryProvider

/** @public */
export declare interface LiveQueryProviderProps {
  children: React.ReactNode
  /**
   * The Sanity client to use for fetching data and listening to mutations.
   */
  client: SanityClient
  /**
   * Reconfigures `client` with the provided `token`, as well as changing its configuration to
   * have `perspective: 'drafts'`, `useCdn: false` and `ignoreBrowserTokenWarning: true`.
   * If you want to use a different configuration, then use just the `client` prop and set the token yourself,
   * for example by: `client={client.withConfig({token})}`
   */
  token?: string
  /** @deprecated these options are no longer used */
  cache?: CacheOptions
  /**
   * @deprecated this option is now always enabled
   */
  turboSourceMap?: boolean
  /**
   * @deprecated no longer used
   */
  refreshInterval?: never
  logger?: Logger
  /**
   * @defaultValue 'drafts'
   */
  perspective?: Exclude<ClientPerspective, 'raw'>
}

/**
 * Specify a `console.log` compatible logger to aid debugging
 * @public
 */
export declare type Logger = typeof console | Pick<typeof console, 'warn' | 'error' | 'log'>

/** @public */
export declare type QueryEnabled = boolean

/** @public */
export declare type QueryLoading = boolean

/**
 * The `useLiveQuery` hook is designed to work in environments where the parent `LiveQueryProvider` may be lazy loaded.
 * Thus if it can't "know" if it's "live" or not, or of it will be later. When everything is setup correctly this is fine.
 * This hook on the other hand does know. If it returns `false` then sibling `useLiveQuery` hooks are not "live".
 * If it returns `true` then sibling `useLiveQuery` hooks are "live" as there is a parent `LiveQueryProvider` in the tree that is loaded and active.
 * @public
 * @deprecated use `useLiveQuery` instead: `const [,,enabled] = useLiveQuery(initialData, query, params)`
 */
export declare function useIsEnabled(): boolean

/** @public */
export declare function useLiveQuery<QueryResult, QueryParams extends QueryParams = QueryParams>(
  initialData: QueryResult,
  query: string,
  queryParams?: QueryParams,
  options?: LiveQueryHookOptions<QueryResult>,
): [QueryResult, QueryLoading, QueryEnabled]

export {}
