declare module "bluebird" {
  interface Disposer {
  }

  interface MapOptions {
    concurrency: number
  }

  class BluebirdPromise<T> implements Promise<T> {
    constructor(callback: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: Error) => void, onCancel?: (handler: () => void) => void) => void)

    static config(options: any): void

    static all<T>(values: Iterable<T | PromiseLike<T>>): BluebirdPromise<Array<T>>

    static map<T>(items: Iterable<T | PromiseLike<T>>, mapper: (item: T) => PromiseLike<any>, opts?: MapOptions): BluebirdPromise<Array<any>>

    static map<T>(items: Iterable<T | PromiseLike<T>>, mapper: (item: T, index: number) => PromiseLike<any>, opts?: MapOptions): BluebirdPromise<Array<any>>

    static mapSeries<T>(items: Iterable<T>, mapper: (item: T) => BluebirdPromise<any>): BluebirdPromise<any>

    static reject(error: Error): BluebirdPromise<any>

    static coroutine(generator: Function): Function

    /**
     * Returns a function that will wrap the given `nodeFunction`. Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function. The node function should conform to node.js convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument.
     *
     * If the `nodeFunction` calls its callback with multiple success values, the fulfillment value will be an array of them.
     *
     * If you pass a `receiver`, the `nodeFunction` will be called as a method on the `receiver`.
     */
    static promisify<T>(func: (callback: (err: any, result: T) => void) => void, receiver?: any): () => BluebirdPromise<T>;
    static promisify<T, A1>(func: (arg1: A1, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1) => BluebirdPromise<T>;
    static promisify<T, A1, A2>(func: (arg1: A1, arg2: A2, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2) => BluebirdPromise<T>;
    static  promisify<T, A1, A2>(func: (arg1: A1, arg2: A2, callback: (error: Error) => void) => void, receiver?: any): (arg1: A1, arg2: A2) => BluebirdPromise<T>;
    static promisify<T, A1, A2, A3>(func: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3) => BluebirdPromise<T>;
    static promisify<T, A1, A2, A3, A4>(func: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => BluebirdPromise<T>;

    static promisify<T, A1, A2, A3, A4, A5>(func: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => BluebirdPromise<T>;

    static promisify(nodeFunction: Function, receiver?: any): Function;

    static resolve<T>(value: T | PromiseLike<T>): BluebirdPromise<T>
    static resolve(): BluebirdPromise<void>

    then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): BluebirdPromise<TResult>

    then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): BluebirdPromise<TResult>

    //noinspection ReservedWordAsName
    catch(onrejected?: (reason: any) => T | PromiseLike<T>): BluebirdPromise<T>
    //noinspection ReservedWordAsName
    catch(onrejected?: (reason: any) => void): BluebirdPromise<T>;

    [Symbol.toStringTag]: any

    disposer(disposer: (result: T, promise: Promise<any>) => Promise<any> | void): Disposer

    thenReturn<T>(result: T): BluebirdPromise<T>

    cancel(): void

    isFulfilled(): boolean

    isPending(): boolean

    isCancelled(): boolean
    
    isRejected(): boolean

    value(): T
  }

  export { BluebirdPromise as Promise }
}