/*!
 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 *
 * 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 {RestfulAPI} from 'restful-js';
import uuid from 'uuid-js';
import md5 from 'md5';

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';

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 applyMD5Header(options, data) {
	if (options.md5) {
		let headers = options.headers;
		headers[CONTENT_MD5_HEADER] = window.btoa(md5(JSON.stringify(data)).toLowerCase());
	}
}

function handleResponse(xhr) {
	let authToken = xhr.getResponseHeader(AUTHORIZATION_HEADER);
	let prevToken = this && this.headers && this.headers[AUTHORIZATION_HEADER];
	if (authToken && authToken !== prevToken) {
		if (authToken === 'null') {
			localStorage.removeItem(STORAGE_AUTH_KEY);
		} else {
			localStorage.setItem(STORAGE_AUTH_KEY, authToken);
		}
	}
}


class RestAPIUtil extends RestfulAPI {

	applySecurity(options, data) {
		let headers = options.headers || (options.headers = {});

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

		let attApiHeaders = Configuration.get('ATTApiHeaders'),
			attUidHeader = attApiHeaders && attApiHeaders.userId;
		if (attUidHeader) {
			headers[attUidHeader.name] = attUidHeader.value;
		}

		headers[REQUEST_ID_HEADER] = uuid.create().toString();
		applyMD5Header(options, data);
	}

	handleRequest(url, type, options = {}, data){
		let success = options.success;
		options.success = function (resp, textStatus, xhr) {
			handleResponse.call(this, xhr);
			if (success) {
				success.call(options.context, {...resp}, textStatus, xhr);
			}
		};

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

}

const instance = new RestAPIUtil({
	errorResponseHandler,
	ajaxStartHandler: () => store.dispatch({type: LoaderConstants.SHOW}),
	ajaxStopHandler: () => store.dispatch({type: LoaderConstants.HIDE})
});

// jQuery binary transport to download files through XHR
// http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/
// https://github.com/henrya/js-jquery/tree/master/BinaryTransport
instance.$.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) {
	// check for conditions and support for blob / arraybuffer response type
	if (window.FormData && ((options.dataType && (options.dataType === 'binary')) ||
		(options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) ||
		(window.Blob && options.data instanceof Blob))))
	) {
		return {
			// create new XMLHttpRequest
			send: function (headers, callback) {
				// setup all letiables
				let xhr = new XMLHttpRequest(),
					url = options.url,
					type = options.type,
					async = options.async || true,
					// blob or arraybuffer. Default is blob
					dataType = options.responseType || 'blob',
					data = options.data || null,
					username = options.username || null,
					password = options.password || null;

				xhr.addEventListener('load', function () {
					let data = {};
					data[options.dataType] = xhr.response;
					// make callback and send data
					callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
				});

				xhr.open(type, url, async, username, password);

				// setup custom headers
				for (let i in headers) {
					xhr.setRequestHeader(i, headers[i]);
				}

				xhr.responseType = dataType;
				xhr.send(data);
			},
			abort: function () {
			}
		};
	}
});

export default instance;
