import axios, {AxiosTransformer} from "axios";
import Vue from "vue";
import Store from "@/store";
import {Message, Notification} from "element-ui";

import config from "../config";
import Util from "./Util";
import CacheStores from "../service/module/CacheStores";
import querystring from "querystring";


/**
 * 根据配置,找到对应的缓存key
 * @param {String} url
 * @param {Object} params
 */
const buildRequestUrl = (url, params) => {
  Util.safety.safeData(params);
  let queryStr = querystring.stringify(params);
  return url + (queryStr ? "?" + queryStr : "");
};

/**
 * 缓存适配
 */
let cacheAdapter = (originAdapter) => {
  return async (option) => {
    if ("get" !== option.method) {
      return originAdapter(option);
    }
    if (true !== option.cache) {
      return originAdapter(option);
    }

    let cacheStore = option['cacheStore'] || CacheStores.ajaxStore;
    let key = buildRequestUrl(option.url, option.params);
    let value = await cacheStore.getItem(key);
    if (null == value || true === option.force) {
      let resp = await originAdapter(option);
      await cacheStore.setItem(key, resp.data);
      return resp;
    }
    return {
      data: value,
      status: 200,
      statusText: "OK",
      headers: {},
      config: option,
      request: {}
    };
  };
};

/**
 * 进度条适配
 */
let progressAdapter = (originAdapter) => {
  return async (option) => {
    if (option.progress === false) {
      return originAdapter(option)
    }
    try {
      Vue.prototype.$Progress.start();
      return await originAdapter(option);
    } finally {
      Vue.prototype.$Progress.finish();
    }
  };
};

/**
 * 下载
 */
let downloadAdapter = (originAdapter) => {
  return async (option) => {
    if (!option.params) {
      return originAdapter(option)
    }
    if (!option.params.agile || !option.params.down) {
      return originAdapter(option)
    }
    Util.downFileIframe(option.url, option.params);
    return {
      data: "",
      status: 200,
      statusText: "OK",
      headers: {},
      config: option,
      request: {}
    };
  };
};


/**
 * 框架处理
 */
let frameAdapter = (originAdapter) => {
  return async (option) => {
    try {
      return originAdapter(option);
    } catch (error) {
      //  从国际化中取,然后看服务器响应的[message],如果不存在,使用状态码文本
      if (error.response) {
        let message = Vue.t("httpError." + error.response.status) || error.response.statusText;
        Notification.error({title: Vue.t("httpError.title"), message: message});
      }
      throw error;
    }
  };
};

// 拦截响应做出处理
let onResponse = (resp) => {

  //请求配置
  let option = resp.config;
  let data = resp.data;

  // 取出 两个数据节点
  let {respCode, respDesc} = data;

  if (!respCode) {
    return data;
  }
  if (!respDesc) {
    return data;
  }

  let canMessage = option.message !== false && typeof (respDesc) == 'string';


  // 服务器处理成功
  if (respCode === config.respCode.success) {
    if ("get" !== option.method) {
      if (canMessage) {
        Message.success({message: respDesc, duration: 1000});
      }
    }
  }

  // 服务器处理失败
  else if (respCode === config.respCode.failure) {
    if (canMessage) {
      Message.error({
        message: respDesc,
        duration: respDesc.length > 20 ? 10000 : 3000,
        dangerouslyUseHTMLString: true
      });
    }
    let error = new Error(respDesc);
    error.data = data;
    throw error;
  }

  //  处理如果超时
  else if (respCode === config.respCode.timeout) {
    if (!config.isSso) {
      Store.base.state.loginTimeout = true;
    }
    let error = new Error(respDesc);
    error.data = data;
    throw error;
  }

  // 处理校验失败
  else if (respCode === config.respCode.validat) {
    let error = new Error(respDesc);
    error.data = data;
    error.validError = respDesc || {};
    throw error;
  }

  //  其他自定义code
  else {
    if (canMessage) {
      Message.warning({
        message: respDesc,
        duration: respDesc.length > 20 ? 10000 : 3000,
        dangerouslyUseHTMLString: true
      });
    }
    let error = new Error(respDesc);
    error.data = data;
    throw error;
  }

  return data;
};

let transformRequest = (data, header) => {
  // 防止非法数据
  Util.safety.preSubmit(data);
  return data;
};


//  应用使用的AJAX库
let ajax = axios.create({
  baseURL: config.ajaxUrl,
  adapter: frameAdapter(downloadAdapter(progressAdapter(cacheAdapter(axios.defaults.adapter)))),
  params: {},
  headers: {'Cache-Control': 'no-cache'},
  timeout: config.tomeOut,
  //防止 RFC 7230 and RFC3986 URL规范
  paramsSerializer(params) {
    params.page && params.page--;
    Util.safety.preSubmit(params);
    return querystring.stringify(params);
  },
  transformRequest: [transformRequest, axios.defaults.transformRequest[0]]
});


ajax.interceptors.response.use(onResponse);

export default ajax;
