'use strict';

var utils = require('./utils.js');
var bind = require('./helpers/bind.js');
var Axios = require('./core/Axios.js');
var mergeConfig = require('./core/mergeConfig.js');
var index = require('./defaults/index.js');
var formDataToJSON = require('./helpers/formDataToJSON.js');
var CanceledError = require('./cancel/CanceledError.js');
var CancelToken = require('./cancel/CancelToken.js');
var isCancel = require('./cancel/isCancel.js');
var data = require('./env/data.js');
var toFormData = require('./helpers/toFormData.js');
var AxiosError = require('./core/AxiosError.js');
var spread = require('./helpers/spread.js');
var isAxiosError = require('./helpers/isAxiosError.js');
var AxiosHeaders = require('./core/AxiosHeaders.js');
var adapters = require('./adapters/adapters.js');
var HttpStatusCode = require('./helpers/HttpStatusCode.js');

/**
 * Create an instance of Axios
 *
 * @param {Object} defaultConfig The default config for the instance
 *
 * @returns {Axios} A new instance of Axios
 */
function createInstance(defaultConfig) {
  const context = new Axios(defaultConfig);
  const instance = bind(Axios.prototype.request, context);

  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context, {allOwnKeys: true});

  // Copy context to instance
  utils.extend(instance, context, null, {allOwnKeys: true});

  // Factory for creating new instances
  instance.create = function create(instanceConfig) {
    return createInstance(mergeConfig(defaultConfig, instanceConfig));
  };

  return instance;
}

// Create the default instance to be exported
const axios = createInstance(index);

// Expose Axios class to allow class inheritance
axios.Axios = Axios;

// Expose Cancel & CancelToken
axios.CanceledError = CanceledError;
axios.CancelToken = CancelToken;
axios.isCancel = isCancel;
axios.VERSION = data.VERSION;
axios.toFormData = toFormData;

// Expose AxiosError class
axios.AxiosError = AxiosError;

// alias for CanceledError for backward compatibility
axios.Cancel = axios.CanceledError;

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};

axios.spread = spread;

// Expose isAxiosError
axios.isAxiosError = isAxiosError;

// Expose mergeConfig
axios.mergeConfig = mergeConfig;

axios.AxiosHeaders = AxiosHeaders;

axios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing);

axios.getAdapter = adapters.getAdapter;

axios.HttpStatusCode = HttpStatusCode;

axios.default = axios;

module.exports = axios;
