'use strict';

var utils = require('./../utils');
var transformData = require('./transformData');

/**
 * Dispatch a request to the server using whichever adapter
 * is supported by the current environment.
 *
 * @param {object} config The config that is to be used for the request
 * @returns {Promise} The Promise to be fulfilled
 */
module.exports = function dispatchRequest(config) {
  // Ensure headers exist
  config.headers = config.headers || {};

  // Transform request data
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // Flatten headers
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers || {}
  );

  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  var adapter;

  if (typeof config.adapter === 'function') {
    // For custom adapter support
    adapter = config.adapter;
  } else if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('../adapters/xhr');
  } else if (typeof process !== 'undefined') {
    // For node use HTTP adapter
    adapter = require('../adapters/http');
  }

  return Promise.resolve(config)
    // Wrap synchronous adapter errors and pass configuration
    .then(adapter)
    .then(function onFulfilled(response) {
      // Transform response data
      response.data = transformData(
        response.data,
        response.headers,
        config.transformResponse
      );

      return response;
    }, function onRejected(error) {
      // Transform response data
      if (error && error.response) {
        error.response.data = transformData(
          error.response.data,
          error.response.headers,
          config.transformResponse
        );
      }

      return Promise.reject(error);
    });
};
