import { AxiosResponse } from "axios";
import { Container } from "inversify";
import { classDef, stringDictionary, ISerializer, typeRef, httpRestVerb } from "@codiac.io/codiac-common";
import { IBetterLogger } from '@codiac.io/codiac-common/IBetterLogger';
import { endpointSpec } from './endpoint-spec';
import { TokenUtils } from './token-utils';
export declare class TypeName {
    static endpointSpec<T>(entityType: classDef<T> | string): string;
    static arrayOf<T>(entityType: classDef<T> | string): string;
    static criteriaFor<T>(entityType: classDef<T> | string): string;
}
export declare abstract class ApiClientBase {
    authToken?: string | undefined;
    static endpointSpecs: Container;
    static serializers: Container;
    static bootstrap_base(endpointsJson: any[], logger?: IBetterLogger): void;
    /** For special serializers (eg: StringFilter, etc).
     * Maps the given serializer for use on the given type
     * when later converting input to an http request.
     * NOTE:  a default serializer will be used if reqd and none has been registered here.
     */
    static registerSerializerFor<T>(valueType: classDef<T> | string, serializer: ISerializer): void;
    /** Returns undefined when no serializer has been registered for the given valueType. */
    static getSerializerFor(valueType: typeRef | string): ISerializer | undefined;
    /** Applied to this.tokenHeaderParam in the ctor.
     *  Typical name of the http request header that declares the authentication token for the request.  */
    static DEFAULT_TOKEN_HEADER_PARAM: string;
    /** Local interface for a remote Api.
     * @param apiRootUrl Override for this.GetDefaultRootUrl().  Fully qualified base url of the api.  That is, prepending it to any individual endpoint route will yield the fully qualified url for that endpoint.
     * @param authToken User token for the api this client is targeting.
     *                  NOTE: Also must get hydrated if child class runs successful attempts of authenticate / refreshToken / switchTenant / registerTenant.
    */
    constructor(logger: IBetterLogger, apiRootUrl?: string, authToken?: string | undefined);
    readonly apiRootUrl: string;
    protected tokenUtils: TokenUtils;
    /** The name of the http request header that declares the authentication token for the request.
     *  NOTE: This gets set to DEFAULT_TOKEN_HEADER_NAME in the ctor of ApiClientBase,
     *        so child classes can override it in their own ctor AFTER calling super(). */
    protected tokenHeaderName: string;
    /** Applied when apiRootUrl is not passed to the ApiClientBase ctor.
     *  The fully qualified url to use as the base for all endpoint paths in the api,
     *  SUGGESTION: Try to load the root url from a config file,
     *  and default to a hard-coded publicly available test environment for the api,
     *  and ship with a config file pointing to the production url. */
    protected abstract GetDefaultRootUrl(): string;
    protected logger: IBetterLogger;
    /** Sets the user context to impersonate in requests made to the api. */
    setUserToken(token: string): void;
    /** Utility method that determines whether
     * the given token is expired, by inspecting its claims. */
    isExpired(token: string, throwOnError?: boolean): boolean;
    /** Utility method that inspects the claims
     * of the given token to acquire its expiration. */
    extractTokenExpiration(token: string): Date | undefined;
    /** Utility method that inspects the claims
     * of the given token to acquire the roles granted to its user. */
    extractRoles(token: string): string[] | undefined;
    /** Retrieves the registered endpoint spec for the given request type and httpMethod.
     *  Throws exception if the given entity type and http method are not found.
     */
    getEndpointFor<TRequest>(entityType: classDef<TRequest> | string, httpMethod: httpRestVerb): endpointSpec<TRequest>;
    /**  Produces the value for the "Authorization" http header in an RFC 2617 Basic Authentication scheme.
     * Consists of the string "Basic " followed by a colon-separated, base64 encoded string of the username and password.
     * eg:  for userid "Aladdin" and password "open sesame", this function will return "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==".
     * @see https://tools.ietf.org/html/rfc2617#page-4 RFC 2617 HTTP Authentication - Assembling the header value for a basic authentication request. */
    protected static buildBasicAuthenticationHeader(userName: string, passwordOrApiKey: string): string;
    /** Fires off an http request to the remote api.
     * Throws any encountered exceptions
     * (api exceptions dont get raised: they get passed back in the response envelope).
     *
     * @param httpVerb
     * @param url Can be relative to this.apiBaseUrl or fully qualified.
     * @param req
     * @param headers
     */
    makeHttpCall<TRequest, TResponse>(httpVerb: httpRestVerb, url: string, req?: Object, headers?: {
        [key: string]: string;
    }): Promise<[TResponse, {
        [key: string]: string;
    }?]>;
    /** Fires off an http request to the remote api,
     * AND RETURNS THE ENTIRE AXIOS RESPONSE.
     * Throws any encountered exceptions
     * (api exceptions dont get raised: they get passed back in the response envelope).
     *
     * @param httpVerb
     * @param url Can be relative to this.apiBaseUrl or fully qualified.
     * @param req
     * @param headers
     */
    makeRawHttpCall<TRequest, TResponse>(httpVerb: httpRestVerb, url: string, req: Object, headers?: {
        [key: string]: string;
    }): Promise<AxiosResponse<TResponse>>;
    /** Performs replacements on the route using
     * the matching values from the given request object
     * @param route  The relative url path for the endpoint including route tokens.
     * @param applyRemainingToQuerystring  (default: false) When set, adds querystring params
     * for every property on the entity that was not already applied to a route token.
     * */
    buildUrl(route: string, request: any, applyRemainingToQuerystring?: boolean): string;
    /** Returns an object containing only properties with primitive values;
     *  no objects, or functions.
     *
     *  NOTE:  DOES include null values (which javascript still considers objects)
     *
     * @see [The world picking up the slack on this failure](https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript/8511350#8511350)
     */
    private extractPrimitiveProperties;
    /** Serializes property values of the given entity
     * whose types have a registered serializer. */
    applyPropertySerializers(entity: any, serializerMap: stringDictionary): any;
    /** Safe to blindly append this to an existing url tat does not yet have a querystring.
     * Returns "?" character if the given obj has properties.
     * Returns "" if the given obj is undefined or empty. */
    private createQueryStringFrom;
    /** Creates a new object from the given object without the given property paths */
    private omit;
    /** Very generic method for executing a POST operation against the api
     *  from an endpoint definition in the registered endpoints collection.
     *  Hydrates any route parameters or required headers for the endpoint
     *  from the given requestContract and routeValues objects.
     *  Throws any exceptions
     *  (because it cant guarantee a response envelope that declares
     *   errors and successes, it cant implement a "try" pattern).
     * @param routeValues Additional key value pairs (beyond the requestContract) to apply to any route parameters for the endpoint.
     */
    post<TRequest extends Object, TResponse>(requestType: classDef<TRequest>, requestContract: TRequest, routeValues?: any): Promise<[TResponse, {
        [header: string]: string;
    }?]>;
    /** Very generic method for executing a PUT operation against the api
     *  from an endpoint definition in the registered endpoints collection.
     *  Hydrates any route parameters or required headers for the endpoint
     *  from the given requestContract and routeValues objects.
     *  Throws any exceptions
     *  (because it cant guarantee a response envelope that declares
     *   errors and successes, it cant implement a "try" pattern).
     * @param routeValues Additional key value pairs (beyond the requestContract) to apply to any route parameters for the endpoint.
     */
    put<TRequest extends Object, TResponse>(requestType: classDef<TRequest>, requestContract: TRequest, routeValues?: any): Promise<[TResponse, {
        [header: string]: string;
    }?]>;
    /** Very generic method for executing a GET operation against the api
     *  from an endpoint definition in the registered endpoints collection.
     *  Hydrates any route parameters or required headers for the endpoint
     *  from the given requestContract and routeValues objects.
     *  Throws any exceptions
     *  (because it cant guarantee a response envelope that declares
     *   errors and successes, it cant implement a "try" pattern).
     * @param routeValues Additional key value pairs (beyond the requestContract) to apply to any route parameters for the endpoint.
     */
    get<TRequest extends Object, TResponse>(requestType: classDef<TRequest>, requestContract: TRequest, routeValues?: any): Promise<[TResponse, {
        [header: string]: string;
    }?]>;
    /** Very generic method for executing a PATCH operation against the api
     *  from an endpoint definition in the registered endpoints collection.
     *  Hydrates any route parameters or required headers for the endpoint
     *  from the given requestContract and routeValues objects.
     *  Throws any exceptions
     *  (because it cant guarantee a response envelope that declares
     *   errors and successes, it cant implement a "try" pattern).
     * @param routeValues Additional key value pairs (beyond the requestContract) to apply to any route parameters for the endpoint.
     */
    patch<TRequest extends Object, TResponse>(requestType: classDef<TRequest>, requestContract: TRequest, routeValues?: any): Promise<[TResponse, {
        [header: string]: string;
    }?]>;
    /** Very generic method for executing a DELETE operation against the api
     *  from an endpoint definition in the registered endpoints collection.
     *  Hydrates any route parameters or required headers for the endpoint
     *  from the given requestContract and routeValues objects.
     *  Throws any exceptions
     *  (because it cant guarantee a response envelope that declares
     *   errors and successes, it cant implement a "try" pattern).
     * @param routeValues Additional key value pairs (beyond the requestContract) to apply to any route parameters for the endpoint.
     */
    delete<TRequest extends Object, TResponse>(requestType: classDef<TRequest>, requestContract: TRequest, routeValues?: any): Promise<[TResponse, {
        [header: string]: string;
    }?]>;
    /** Very generic method for executing an http operation against the api
     *  from an endpoint definition in the registered endpoints collection.
     *  Hydrates any route parameters or required headers for the endpoint
     *  from the given requestContract and routeValues objects.
     *  Throws any exceptions
     *  (because it cant guarantee a response envelope that declares
     *   errors and successes, it cant implement a "try" pattern).
     * @param routeValues Additional key value pairs (beyond the requestContract) to apply to any route parameters for the endpoint.
     */
    protected hitConfiguredEndpoint<TRequest extends Object, TResponse>(requestType: classDef<TRequest>, httpVerb: httpRestVerb, requestContract: TRequest, routeValues?: any): Promise<[TResponse, {
        [header: string]: string;
    }?]>;
}
