import isObj from './isObj';
import isArr from './isArr';
import isFun from './isFun';
import getCookie from './getCookie';
import stringifyQueryString from './stringifyQueryString';

/**
 * 创建一个基于axios的http请求实例
 *
 * 注意：此方法依赖`axios`包，使用前请确保项目中已经安装该依赖
 * 如果还未安装，可以运行`npm install axios --save`进行安装
 *
 * @param axios axios对象
 * @param options 创建参数
 * @returns {Promise<any>}
 *
 * @example
 * import axios from 'axios';
 *
 * const http = createHttp(axios);
 * const {resToArr, resToObj} = http;
 *
 * // Get请求，格式化结果为数组
 * const querySomeArrayData = () => {
 *   return http.get('https://api.bilibili.com/xxx').then(resToArr);
 * }
 * // Post请求，格式化结果为对象
 * const requestSomeObjData = (data) => {
 *   return http.post('https://api.bilibili.com/xxx', data).then(resToObj);
 * }
 *
 * // 可以放心解构返回结果，已做空值保护处理
 * querySomeArrayData()
 *   .then(([ firstItem ]) => {
 *     console.log(firstItem);
 *   })
 *   .catch((err) => {
 *     console.error(err)
 *   });
 * requestSomeObjData()
 *   .then(({ objField }) => {
 *     console.log(objField);
 *   })
 *   .catch((err) => {
 *     console.error(err)
 *   });
 *
 * // 单个接口不判断res.code===0是成功
 * http.get('https://api.bilibili.com/xxx', { handleResCode: false }).then(res => {
 *   console.log(res)
 * });
 */
function createHttp(axios, options) {
  options = options || {};
  var instance = axios.create(options.axiosOptions || {});
  Object.assign(instance.defaults, {
    withCredentials: true
  }, options.defaults);

  // 请求拦截器
  var reqInterceptor = options.reqInterceptor || function (reqConf) {
    return reqConf;
  };

  // 请求失败拦截器
  var reqErrInterceptor = options.reqErrInterceptor || function (err) {
    console.error(err);
    return Promise.reject(err);
  };

  // 响应拦截器
  var resInterceptor = options.resInterceptor || function (res) {
    var isHandleCode = options.handleResCode !== false && res.config.handleResCode !== false;

    if (isHandleCode && res.data.code !== 0) {
      return Promise.reject(res.data);
    }

    return res.data;
  };

  // 响应失败拦截器
  var resErrInterceptor = options.resErrInterceptor || function (err) {
    console.error(err);
    return Promise.reject(err);
  };

  // Get处理方法
  var getHandler = options.getHandler || function (http, url, opts) {
    opts = opts || {};
    return http.get(url, opts);
  };

  // Post处理方法
  var postHandler = options.postHandler || function (http, url, data, opts) {
    data = data || {};
    opts = opts || {};
    var formType = 'application/x-www-form-urlencoded';
    var headers = Object.assign({}, {
      'Content-Type': formType
    }, opts.headers);

    if (isFun(opts.getCsrf)) {
      data.csrf = opts.getCsrf();
      delete opts.getCsrf;
    } else if (isFun(options.getCsrf)) {
      data.csrf = options.getCsrf();
    } else {
      data.csrf = getCookie('bili_jct');
    }

    if (headers['Content-Type'] === formType || headers['content-type'] === formType) {
      data = stringifyQueryString(data);
    }

    return http.post(url, data, Object.assign(opts, {
      headers: headers
    }));
  };

  instance.interceptors.request.use(reqInterceptor, reqErrInterceptor);
  instance.interceptors.response.use(resInterceptor, resErrInterceptor);
  return {

    /**
     * Get请求
     */
    get: function get(url, opts) {
      return getHandler(instance, url, opts);
    },

    /**
     * Post请求
     */
    post: function post(url, data, opts) {
      return postHandler(instance, url, data, opts);
    },

    /**
     * Put请求
     */
    put: function put(url, data, opts) {
      data = data || {};
      opts = opts || {};
      return instance.put(url, data, opts);
    },

    /**
     * Delete请求
     */
    "delete": function _delete(url, opts) {
      opts = opts || {};
      return instance["delete"](url, opts);
    },

    /**
     * Patch请求
     */
    patch: function patch(url, data, opts) {
      data = data || {};
      opts = opts || {};
      return instance.patch(url, data, opts);
    },

    /**
     * Request请求
     */
    request: function request(opts) {
      opts = opts || {};
      return instance.request(opts);
    },
    resToData: resToData,
    resToObj: resToObj,
    resToArr: resToArr,
    resToPage: resToPage
  };
}

Object.assign(createHttp, {
  resToData: resToData,
  resToObj: resToObj,
  resToArr: resToArr,
  resToPage: resToPage
});

/**
 * 获取返回结果的data字段
 */
function resToData(res) {
  return res && res.data || null;
}

/**
 * 获取返回结果data字段转对象
 */
function resToObj(res) {
  return res && isObj(res.data) && res.data || {};
}

/**
 * 获取返回结果data字段转数组
 */
function resToArr(res) {
  return res && isArr(res.data) && res.data || {};
}

/**
 * 获取返回结果data字段转分页对象
 */
function resToPage(res) {
  var data = res && isObj(res.data) && res.data || {};
  data.total = data.total || 0;
  data.list = isArr(data.list) && data.list || [];
  return data;
}

export default createHttp;
