import { AxiosRequestConfig, AxiosInstance } from "axios"
import * as React from "react"
import { Store } from "pullstate"
export {
    AxiosRequestConfig, 
    AxiosInstance
}
export interface IContextInstance {
    get: Function,
    post: Function,
    delete: Function,
    put: Function,
    request: Function
}

export interface IContextArgs<T extends object = {}> {
    auth: Store<T>
}

export interface IHttpClient<A> {
    get: <T = any, P = Record<string, any>>(url: string, params?: P, requestConfig?: A) => Promise<T>,
    post: <T = any, P = Record<string, any>>(url: string, params?: P, requestConfig?: A) => Promise<T>,
    delete: <T = any, P = Record<string, any>>(url: string, params?: P, requestConfig?: A) => Promise<T>,
    put: <T = any, P = Record<string, any>>(url: string, params?: P, requestConfig?: A) => Promise<T>,
    request: <T = any>(requestConfig?: A) => Promise<T>,
}
/**
 * @param callback 
 */
export function createHttpClient<T,S>(callback?: (e: S) => S): IHttpClient<T>

export type IContextInstanceReturnType<T extends IContextInstance> = Pick<T, "get" | "post" | "delete" | "put" | "request">

export interface IContext<T extends IContextInstance, S extends object = {}> extends IContextInstanceReturnType<T>, IContextArgs<S> { }

export function useApi<T extends IContext<IContextInstance>>(): T

export interface IApiProviderParam<T extends IContextInstance,S extends object = {}> {
    httpClient: T
    children?: React.ReactElement
    initAuth?: S
}

export function ApiProvider<T extends IContextInstance,S extends Object = {}>(apiProviderParam: IApiProviderParam<T,S>): JSX.Element
export type IRemoveFirst<T extends any[]> = T['length'] extends 0 ? [] : (((...b: T) => void) extends (a: any, ...b: infer I) => void ? I : [])
export type IAsyncReturnType<T extends (...args: any) => any> = ReturnType<T> extends Promise<infer R> ? R : T
export function useApiState<T extends (context: S, ...args: any[]) => any, S extends IContext<IContextInstance>>(context: S, call: T, ...args: IRemoveFirst<Parameters<T>>): [IAsyncReturnType<T>, boolean, Error]

export function useApiAnyLoading<T extends IContext<IContextInstance>>(context: T): boolean
export function useApiAnyError<T extends IContext<IContextInstance>>(context: T): Error
