/*
 * Copyright © 2016-2018 European Support Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import uuid from 'uuid-js';
import md5 from 'md5';
import axios from 'axios';

import store from 'sdc-app/AppStore.js';
import { actionTypes as LoaderConstants } from 'nfvo-components/loader/LoaderConstants.js';
import Configuration from 'sdc-app/config/Configuration.js';
import errorResponseHandler from './ErrorResponseHandler.js';

//methods
const GET = 'GET';
const POST = 'POST';
const PUT = 'PUT';
const DELETE = 'DELETE';

// content-types
const APPLICATION_JSON = 'application/json';
const MULTIPART_FORM_DATA = 'multipart/form-data';

const BINARY = 'binary';

const AUTHORIZATION_HEADER = 'X-AUTH-TOKEN';
const STORAGE_AUTH_KEY = 'sdc-auth-token';
const REQUEST_ID_HEADER = 'X-ECOMP-RequestID';
const CONTENT_MD5_HEADER = 'Content-MD5';

function applySecurity(options, data) {
    let headers = options.headers || (options.headers = {});
    if (options.isAnonymous) {
        return;
    }

    let authToken = localStorage.getItem(STORAGE_AUTH_KEY);
    if (authToken) {
        headers[AUTHORIZATION_HEADER] = authToken;
    }

    let catalogApiHeaders = Configuration.get('CatalogApiHeaders'),
        catalogUidHeader = catalogApiHeaders && catalogApiHeaders.userId;
    if (catalogUidHeader) {
        headers[catalogUidHeader.name] = catalogUidHeader.value;
    }

    headers[REQUEST_ID_HEADER] = uuid.create().toString();
    if (options.md5) {
        let headers = options.headers;
        headers[CONTENT_MD5_HEADER] = window.btoa(
            md5(JSON.stringify(data)).toLowerCase()
        );
    }
}

function handleSuccess(responseHeaders, requestHeaders) {
    let authToken = responseHeaders[AUTHORIZATION_HEADER];
    let prevToken = requestHeaders && requestHeaders[AUTHORIZATION_HEADER];
    if (authToken && authToken !== prevToken) {
        if (authToken === 'null') {
            localStorage.removeItem(STORAGE_AUTH_KEY);
        } else {
            localStorage.setItem(STORAGE_AUTH_KEY, authToken);
        }
    }
}

class RestAPIUtil {
    handleRequest(url, type, options = {}, data) {
        if (DEBUG) {
            console.log('axios --> Making REST call (' + type + '): ' + url);
        }

        applySecurity(options, data);

        // TODO see ig necessary or in transformrequest funtion
        if (type === POST || type === PUT) {
            if (data instanceof FormData) {
                options.headers.contentType = MULTIPART_FORM_DATA;
            } else {
                options.headers.contentType = APPLICATION_JSON;
                //				config.data = JSON.stringify(data);
            }
        } else {
            data = null;
        }

        let config = {
            method: type,
            url: url,
            headers: options.headers,
            data: data
        };

        store.dispatch({ type: LoaderConstants.SEND_REQUEST, url: url });
        if (options.dataType === BINARY) {
            config.responseType = 'arraybuffer';
            return axios(config)
                .then(result => {
                    store.dispatch({
                        type: LoaderConstants.RECEIVE_RESPONSE,
                        url: result.config.url
                    });
                    return {
                        blob: new Blob([result.data]),
                        headers: result.headers
                    };
                })
                .catch(error => {
                    store.dispatch({
                        type: LoaderConstants.RECEIVE_RESPONSE,
                        url: error.config.url
                    });
                    errorResponseHandler(error.response);
                });
        } else {
            return axios(config)
                .then(result => {
                    store.dispatch({
                        type: LoaderConstants.RECEIVE_RESPONSE,
                        url: result.config.url
                    });
                    handleSuccess(result.headers, result.config.headers);
                    return result.data;
                })
                .catch(error => {
                    store.dispatch({
                        type: LoaderConstants.RECEIVE_RESPONSE,
                        url: error.config.url
                    });
                    errorResponseHandler(error.response);
                    return Promise.reject({
                        responseJSON: error.response.data
                    });
                });
        }
    }

    fetch(url, options) {
        return this.handleRequest(url, GET, options);
    }

    get(url, options) {
        return this.fetch(url, options);
    }

    post(url, data, options) {
        return this.handleRequest(url, POST, options, data);
    }

    put(url, data, options) {
        return this.handleRequest(url, PUT, options, data);
    }

    destroy(url, options) {
        return this.handleRequest(url, DELETE, options);
    }
}

const instance = new RestAPIUtil();

export default instance;
