import request = require('request');
import promise = require('bluebird');
import http = require('http');

// ===============================================
// This file is autogenerated - Please do not edit
// ===============================================

/* tslint:disable:no-unused-variable */

export class User {
    id: number;
    username: string;
    firstName: string;
    lastName: string;
    email: string;
    password: string;
    phone: string;
    /**
    * User Status
    */
    userStatus: number;
}

export class Category {
    id: number;
    name: string;
}

export class Pet {
    id: number;
    category: Category;
    name: string;
    photoUrls: Array<string>;
    tags: Array<Tag>;
    /**
    * pet status in the store
    */
    status: Pet.StatusEnum;
}

export namespace Pet {
    export enum StatusEnum { 
        available = <any> 'available',
        pending = <any> 'pending',
        sold = <any> 'sold',
    }
}
export class Tag {
    id: number;
    name: string;
}

export class Order {
    id: number;
    petId: number;
    quantity: number;
    shipDate: Date;
    /**
    * Order Status
    */
    status: Order.StatusEnum;
    complete: boolean;
}

export namespace Order {
    export enum StatusEnum { 
        placed = <any> 'placed',
        approved = <any> 'approved',
        delivered = <any> 'delivered',
    }
}

interface Authentication {
    /**
    * Apply authentication settings to header and query params.
    */
    applyToRequest(requestOptions: request.Options): void;
}

class HttpBasicAuth implements Authentication {
    public username: string;
    public password: string;
    applyToRequest(requestOptions: request.Options): void {
        requestOptions.auth = {
            username: this.username, password: this.password
        }
    }
}

class ApiKeyAuth implements Authentication {
    public apiKey: string;

    constructor(private location: string, private paramName: string) {
    }

    applyToRequest(requestOptions: request.Options): void {
        if (this.location == "query") {
            (<any>requestOptions.qs)[this.paramName] = this.apiKey;
        } else if (this.location == "header") {
            requestOptions.headers[this.paramName] = this.apiKey;
        }
    }
}

class OAuth implements Authentication {
    public accessToken: string;

    applyToRequest(requestOptions: request.Options): void {
        requestOptions.headers["Authorization"] = "Bearer " + this.accessToken;
    }
}

class VoidAuth implements Authentication {
    public username: string;
    public password: string;
    applyToRequest(requestOptions: request.Options): void {
        // Do nothing
    }
}

export class UserApi {
    protected basePath = 'http://petstore.swagger.io/v2';
    protected defaultHeaders : any = {};



    public authentications = {
        'default': <Authentication>new VoidAuth(),
        'api_key': new ApiKeyAuth('header', 'api_key'),
        'petstore_auth': new OAuth(),
    }

    constructor(basePath?: string);
    constructor(basePathOrUsername: string, password?: string, basePath?: string) {
        if (password) {
            if (basePath) {
                this.basePath = basePath;
            }
        } else {
            if (basePathOrUsername) {
                this.basePath = basePathOrUsername
            }
        }
    }

    set apiKey(key: string) {
        this.authentications.api_key.apiKey = key;
    }

    set accessToken(token: string) {
        this.authentications.petstore_auth.accessToken = token;
    }
    private extendObj<T1,T2>(objA: T1, objB: T2) {
        for(let key in objB){
            if(objB.hasOwnProperty(key)){
                objA[key] = objB[key];
            }
        }
        return <T1&T2>objA;
    }
    /**
     * Create user
     * This can only be done by the logged in user.
     * @param body Created user object
     */
    public createUser (body?: User) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/user';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Creates list of users with given input array
     * 
     * @param body List of user object
     */
    public createUsersWithArrayInput (body?: Array<User>) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/user/createWithArray';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Creates list of users with given input array
     * 
     * @param body List of user object
     */
    public createUsersWithListInput (body?: Array<User>) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/user/createWithList';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Logs user into the system
     * 
     * @param username The user name for login
     * @param password The password for login in clear text
     */
    public loginUser (username?: string, password?: string) : Promise<{ response: http.ClientResponse; body: string;  }> {
        const path = this.basePath + '/user/login';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        if (username !== undefined) {
            queryParameters['username'] = username;
        }

        if (password !== undefined) {
            queryParameters['password'] = password;
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: string;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Logs out current logged in user session
     * 
     */
    public logoutUser () : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/user/logout';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Get user by user name
     * 
     * @param username The name that needs to be fetched. Use user1 for testing.
     */
    public getUserByName (username: string) : Promise<{ response: http.ClientResponse; body: User;  }> {
        const path = this.basePath + '/user/{username}'
            .replace('{' + 'username' + '}', String(username));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'username' is set
        if (!username) {
            throw new Error('Missing required parameter username when calling getUserByName');
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: User;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Updated user
     * This can only be done by the logged in user.
     * @param username name that need to be deleted
     * @param body Updated user object
     */
    public updateUser (username: string, body?: User) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/user/{username}'
            .replace('{' + 'username' + '}', String(username));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'username' is set
        if (!username) {
            throw new Error('Missing required parameter username when calling updateUser');
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'PUT',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Delete user
     * This can only be done by the logged in user.
     * @param username The name that needs to be deleted
     */
    public deleteUser (username: string) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/user/{username}'
            .replace('{' + 'username' + '}', String(username));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'username' is set
        if (!username) {
            throw new Error('Missing required parameter username when calling deleteUser');
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'DELETE',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
}
export class PetApi {
    protected basePath = 'http://petstore.swagger.io/v2';
    protected defaultHeaders : any = {};



    public authentications = {
        'default': <Authentication>new VoidAuth(),
        'api_key': new ApiKeyAuth('header', 'api_key'),
        'petstore_auth': new OAuth(),
    }

    constructor(basePath?: string);
    constructor(basePathOrUsername: string, password?: string, basePath?: string) {
        if (password) {
            if (basePath) {
                this.basePath = basePath;
            }
        } else {
            if (basePathOrUsername) {
                this.basePath = basePathOrUsername
            }
        }
    }

    set apiKey(key: string) {
        this.authentications.api_key.apiKey = key;
    }

    set accessToken(token: string) {
        this.authentications.petstore_auth.accessToken = token;
    }
    private extendObj<T1,T2>(objA: T1, objB: T2) {
        for(let key in objB){
            if(objB.hasOwnProperty(key)){
                objA[key] = objB[key];
            }
        }
        return <T1&T2>objA;
    }
    /**
     * Update an existing pet
     * 
     * @param body Pet object that needs to be added to the store
     */
    public updatePet (body?: Pet) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/pet';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'PUT',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Add a new pet to the store
     * 
     * @param body Pet object that needs to be added to the store
     */
    public addPet (body?: Pet) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/pet';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Finds Pets by status
     * Multiple status values can be provided with comma seperated strings
     * @param status Status values that need to be considered for filter
     */
    public findPetsByStatus (status?: Array<string>) : Promise<{ response: http.ClientResponse; body: Array<Pet>;  }> {
        const path = this.basePath + '/pet/findByStatus';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        if (status !== undefined) {
            queryParameters['status'] = status;
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: Array<Pet>;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Finds Pets by tags
     * Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.
     * @param tags Tags to filter by
     */
    public findPetsByTags (tags?: Array<string>) : Promise<{ response: http.ClientResponse; body: Array<Pet>;  }> {
        const path = this.basePath + '/pet/findByTags';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        if (tags !== undefined) {
            queryParameters['tags'] = tags;
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: Array<Pet>;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Find pet by ID
     * Returns a pet when ID &lt; 10.  ID &gt; 10 or nonintegers will simulate API error conditions
     * @param petId ID of pet that needs to be fetched
     */
    public getPetById (petId: number) : Promise<{ response: http.ClientResponse; body: Pet;  }> {
        const path = this.basePath + '/pet/{petId}'
            .replace('{' + 'petId' + '}', String(petId));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'petId' is set
        if (!petId) {
            throw new Error('Missing required parameter petId when calling getPetById');
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: Pet;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.api_key.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Updates a pet in the store with form data
     * 
     * @param petId ID of pet that needs to be updated
     * @param name Updated name of the pet
     * @param status Updated status of the pet
     */
    public updatePetWithForm (petId: string, name?: string, status?: string) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/pet/{petId}'
            .replace('{' + 'petId' + '}', String(petId));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'petId' is set
        if (!petId) {
            throw new Error('Missing required parameter petId when calling updatePetWithForm');
        }

        let useFormData = false;

        if (name !== undefined) {
            formParams['name'] = name;
        }

        if (status !== undefined) {
            formParams['status'] = status;
        }

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Deletes a pet
     * 
     * @param petId Pet id to delete
     * @param apiKey 
     */
    public deletePet (petId: number, apiKey?: string) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/pet/{petId}'
            .replace('{' + 'petId' + '}', String(petId));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'petId' is set
        if (!petId) {
            throw new Error('Missing required parameter petId when calling deletePet');
        }

        headerParams['api_key'] = apiKey;

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'DELETE',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * uploads an image
     * 
     * @param petId ID of pet to update
     * @param additionalMetadata Additional data to pass to server
     * @param file file to upload
     */
    public uploadFile (petId: number, additionalMetadata?: string, file?: any) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/pet/{petId}/uploadImage'
            .replace('{' + 'petId' + '}', String(petId));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'petId' is set
        if (!petId) {
            throw new Error('Missing required parameter petId when calling uploadFile');
        }

        let useFormData = false;

        if (additionalMetadata !== undefined) {
            formParams['additionalMetadata'] = additionalMetadata;
        }

        if (file !== undefined) {
            formParams['file'] = file;
        }
        useFormData = true;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.petstore_auth.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
}
export class StoreApi {
    protected basePath = 'http://petstore.swagger.io/v2';
    protected defaultHeaders : any = {};



    public authentications = {
        'default': <Authentication>new VoidAuth(),
        'api_key': new ApiKeyAuth('header', 'api_key'),
        'petstore_auth': new OAuth(),
    }

    constructor(basePath?: string);
    constructor(basePathOrUsername: string, password?: string, basePath?: string) {
        if (password) {
            if (basePath) {
                this.basePath = basePath;
            }
        } else {
            if (basePathOrUsername) {
                this.basePath = basePathOrUsername
            }
        }
    }

    set apiKey(key: string) {
        this.authentications.api_key.apiKey = key;
    }

    set accessToken(token: string) {
        this.authentications.petstore_auth.accessToken = token;
    }
    private extendObj<T1,T2>(objA: T1, objB: T2) {
        for(let key in objB){
            if(objB.hasOwnProperty(key)){
                objA[key] = objB[key];
            }
        }
        return <T1&T2>objA;
    }
    /**
     * Returns pet inventories by status
     * Returns a map of status codes to quantities
     */
    public getInventory () : Promise<{ response: http.ClientResponse; body: { [key: string]: number; };  }> {
        const path = this.basePath + '/store/inventory';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: { [key: string]: number; };  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.api_key.applyToRequest(requestOptions);

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Place an order for a pet
     * 
     * @param body order placed for purchasing the pet
     */
    public placeOrder (body?: Order) : Promise<{ response: http.ClientResponse; body: Order;  }> {
        const path = this.basePath + '/store/order';
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: Order;  }>();

        let requestOptions: request.Options = {
            method: 'POST',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
            body: body,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Find purchase order by ID
     * For valid response try integer IDs with value &lt;= 5 or &gt; 10. Other values will generated exceptions
     * @param orderId ID of pet that needs to be fetched
     */
    public getOrderById (orderId: string) : Promise<{ response: http.ClientResponse; body: Order;  }> {
        const path = this.basePath + '/store/order/{orderId}'
            .replace('{' + 'orderId' + '}', String(orderId));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'orderId' is set
        if (!orderId) {
            throw new Error('Missing required parameter orderId when calling getOrderById');
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body: Order;  }>();

        let requestOptions: request.Options = {
            method: 'GET',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
    /**
     * Delete purchase order by ID
     * For valid response try integer IDs with value &lt; 1000. Anything above 1000 or nonintegers will generate API errors
     * @param orderId ID of the order that needs to be deleted
     */
    public deleteOrder (orderId: string) : Promise<{ response: http.ClientResponse; body?: any;  }> {
        const path = this.basePath + '/store/order/{orderId}'
            .replace('{' + 'orderId' + '}', String(orderId));
        let queryParameters: any = {};
        let headerParams: any = this.extendObj({}, this.defaultHeaders);
        let formParams: any = {};


        // verify required parameter 'orderId' is set
        if (!orderId) {
            throw new Error('Missing required parameter orderId when calling deleteOrder');
        }

        let useFormData = false;

        let deferred = promise.defer<{ response: http.ClientResponse; body?: any;  }>();

        let requestOptions: request.Options = {
            method: 'DELETE',
            qs: queryParameters,
            headers: headerParams,
            uri: path,
            json: true,
        }

        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }

        request(requestOptions, (error, response, body) => {
            if (error) {
                deferred.reject(error);
            } else {
                if (response.statusCode >= 200 && response.statusCode <= 299) {
                    deferred.resolve({ response: response, body: body });
                } else {
                    deferred.reject({ response: response, body: body });
                }
            }
        });

        return deferred.promise;
    }
}
