{{! Copyright(c) 1995 - 2018 T-Systems Multimedia Solutions GmbH }}
{{! Riesaer Str. 5, 01129 Dresden }}
{{! All rights reserved. }}
{{^useRxJS6}}
import { Observable } from 'rxjs/Observable';
{{/useRxJS6}}
{{#useRxJS6}}
import { Observable } from 'rxjs';
{{/useRxJS6}}

export interface ConfigurationParameters {
    apiKeys?: {[ key: string ]: string};
    username?: string;
    password?: string;
    accessToken?: string | (() => string);
    errorHandler?: (err: any, operationName: string) => Observable<never>;
    beforeHandler?: (operationName: string, method: string) => void;
    afterHandler?: (operationName: string, method: string, result: any) => void;
    defaultHeaderValue?: (headerName: string, operationName: string) => string;
    basePath?: string;
    withCredentials?: boolean;
}

export class Configuration {
    apiKeys?: {[ key: string ]: string};
    username?: string;
    password?: string;
    accessToken?: string | (() => string);
    errorHandler?: (err: any, operationName: string) => Observable<never>;
    beforeHandler?: (operationName: string, method: string) => void;
    afterHandler?: (operationName: string, method: string, result: any) => void;
    defaultHeaderValue?: (headerName: string, operationName: string) => string;
    basePath?: string;
    withCredentials?: boolean;

    constructor(configurationParameters: ConfigurationParameters = {}) {
        this.apiKeys = configurationParameters.apiKeys;
        this.username = configurationParameters.username;
        this.password = configurationParameters.password;
        this.accessToken = configurationParameters.accessToken;
        this.errorHandler = configurationParameters.errorHandler;
        this.beforeHandler = configurationParameters.beforeHandler;
        this.afterHandler = configurationParameters.afterHandler;
        this.defaultHeaderValue = configurationParameters.defaultHeaderValue;
        this.basePath = configurationParameters.basePath;
        this.withCredentials = configurationParameters.withCredentials;
    }

    /**
     * Select the correct content-type to use for a request.
     * Uses {@link Configuration#isJsonMime} to determine the correct content-type.
     * If no content type is found return the first found type if the contentTypes is not empty
     * @param contentTypes - the array of content types that are available for selection
     * @returns the selected content-type or <code>undefined</code> if no selection could be made.
     */
    public selectHeaderContentType (contentTypes: string[]): string | undefined {
        if (contentTypes.length === 0) {
            return undefined;
        }

        let type = contentTypes.find(x => this.isJsonMime(x));
        if (type === undefined) {
            return contentTypes[0];
        }
        return type;
    }

    /**
     * Select the correct accept content-type to use for a request.
     * Uses {@link Configuration#isJsonMime} to determine the correct accept content-type.
     * If no content type is found return the first found type if the contentTypes is not empty
     * @param accepts - the array of content types that are available for selection.
     * @returns the selected content-type or <code>undefined</code> if no selection could be made.
     */
    public selectHeaderAccept(accepts: string[]): string | undefined {
        if (accepts.length === 0) {
            return undefined;
        }

        let type = accepts.find(x => this.isJsonMime(x));
        if (type === undefined) {
            return accepts[0];
        }
        return type;
    }

    /**
     * Check if the given MIME is a JSON MIME.
     * JSON MIME examples:
     *   application/json
     *   application/json; charset=UTF8
     *   APPLICATION/JSON
     *   application/vnd.company+json
     * @param mime - MIME (Multipurpose Internet Mail Extensions)
     * @return True if the given MIME is JSON, false otherwise.
     */
    public isJsonMime(mime: string): boolean {
        const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
        return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
    }
}
