export const listenerKey='_ajaxProxyInstance_listener_'
export const receiveKey='_ajaxProxyInstance_receive_'
export const script=`
const _ajaxProxyInstance = {
  oriXhr: window.XMLHttpRequest,
  oriFetch: window.fetch.bind(window),
  listenerKey:'_ajaxProxyInstance_listener_',
  receiveKey:'_ajaxProxyInstance_receive_',
  interceptor:{
    request:{handler:[],use:(func)=>{if (func && typeof func === 'function'){_ajaxProxyInstance.interceptor.request.handler.push(func)}}},
    response:{handler:[],use:(func)=>{if (func && typeof func === 'function'){_ajaxProxyInstance.interceptor.response.handler.push(func)}}}
  },
  xhr: function () {
    const isObjectOrArray=(source)=>{
      var type = Object.prototype.toString.call(source);
      var res = type === '[object Array]' || type === '[object Object]';
      return res;
    }
    //转换为json
    const toJson=(str)=>{
      let json=str
      try{
        json=JSON.parse(str)
      }catch(e){

      }
      return json
    }
    //请求参数
    let req={url:'',method:'GET',headers:{},data:{}}
    const xhr = new _ajaxProxyInstance.oriXhr;
    const handler=_ajaxProxyInstance.interceptor.request.handler
    const processHandler=()=>{
      for (let i = 0; i < handler.length; ++i) {
        req=handler[i].call(this, req,_ajaxProxyInstance.xhr)
      }
      return req;
    }
    const oriXhr = new _ajaxProxyInstance.oriXhr;
    for (const property in oriXhr) {
      if (property === 'onreadystatechange') {
        oriXhr.onreadystatechange = (...args) => {
          // 下载成功
          if (this.readyState === 4) {
            // console.log('ajax response----',req.url,xhr.responseText)
            //axios请求参数---需要重写的参数
            let options={
              url:req.url,
              method:req.method,
              data:req.data,
              headers:req.headers,
              status: xhr.status,
              statusText: '',
              response:xhr.response,
              responseHeaders: xhr.responseHeaders,//响应时返回响应header
            }
            if (xhr.status === 200&&xhr.responseText){// 判断是否有success方法并执行
              const resContentType=xhr.getResponseHeader("Content-Type")
              if(resContentType.includes('application/json')){
                //将json字符串转换为json对象
                options.response=toJson(xhr.responseText)
              }
            }
            //拦截处理
            let handlers=_ajaxProxyInstance.interceptor.response.handler
            for(let i=0;i<handlers.length;i++){
              options=handlers[i].call(this, options,_ajaxProxyInstance.xhr)
            }
            //重写结果
            xhr.responseText=isObjectOrArray(options.response)?JSON.stringify(options.response):options.response
            xhr.response=isObjectOrArray(options.response)?JSON.stringify(options.response):options.response
          }
          this.onreadystatechange && this.onreadystatechange.apply(this, args);
        }
        this.onreadystatechange = null;
        continue;
      } else if (property === 'onload') {
        
      } else if (property === 'open') {
        this.open = (...args) => {
          const [method, url] = args;
          req.url=url
          req.method=method
          //处理拦截器
          req=processHandler()
          //重写请求
          args[0]=req.method
          args[1]=req.url
          oriXhr.open && oriXhr.open.apply(oriXhr, args);
        }
        continue;
      } else if (property === 'setRequestHeader') {
        this.setRequestHeader = (...args) => {
          let header={[args[0]]: args[1]}
          req.headers=Object.assign(req.headers,header)
          //处理拦截器
          req=processHandler()
          //重写请求---默认最后一个加入的key为当前key
          let keys=Object.keys(req.headers)
          args[0]=keys[keys.length-1]
          args[1]=req.headers[args[0]]
          oriXhr.setRequestHeader && oriXhr.setRequestHeader.apply(oriXhr, args);
        }
        continue;
      } else if (property === 'send') {
        this.send = (...args) => {
          //发送数据
          if(!['get','put',''].includes(req.method.toLocaleLowerCase())){
            let body=args[0]
            req.data=body&&isObjectOrArray(body)?body:toJson(body)
            //处理拦截器
            req=processHandler()
            //重写请求---数据
            args[0]=req.data||arg[0]
          }
          oriXhr.send && oriXhr.send.apply(oriXhr, args);
        }
        continue;
      }
      if (typeof oriXhr[property] === 'function') {
        this[property] = oriXhr[property].bind(oriXhr);
      } else {
        // responseText和response不是writeable的，但拦截时需要修改它，所以修改就存储在this[\``+'_${property}'+`\`]上
        if (['responseText', 'response', 'status'].includes(property)) {
          Object.defineProperty(this, property, {
            get: () => this[\``+'_${property}'+`\`] == undefined ? oriXhr[property] : this[\``+'_${property}'+`\`],
            set: (val) => this[\``+'_${property}'+`\`] = val,
            enumerable: true
          });
        } else {
          Object.defineProperty(this, property, {
            get: () => oriXhr[property],
            set: (val) => oriXhr[property] = val,
            enumerable: true
          });
        }
      }
    }
  },
  fetch: function (...args) {
    const isObjectOrArray=(source)=>{
      var type = Object.prototype.toString.call(source);
      var res = type === '[object Array]' || type === '[object Object]';
      return res;
    }
    //转换为json
    const toJson=(str)=>{
      let json=str
      try{
        json=JSON.parse(str)
      }catch(e){

      }
      return json
    }
    let [url,opts]=args
    let req={
      url,
      method:opts?.method,
      data:!opts?.body||isObjectOrArray(opts?.body)?opts?.body:toJson(opts?.body),
      headers:opts?.headers,
    }
    const processHandler=(handler,...args)=>{
      for (let i = 0; i < handler.length; ++i) {
        req=handler[i].call(this, req,_ajaxProxyInstance.fetch)
      }
      args[0]=req.url||args[0]
      if(!opts){
        opts={}
      }
      opts['method']=req.method||opts?.method
      opts['body']=req.data||opts?.body
      opts['body']=isObjectOrArray(opts['body'])?JSON.stringify(opts['body']):opts['body']
      opts['headers']=req.headers||opts?.headers
      args[1]=opts;
      return args
    }
    
    const getBody = async (stream) => {
      let text = '';
      const decoder = new TextDecoder('utf-8');
      const reader = stream.getReader();
      const processData = (result) => {
        if (result.done) {
          return text;
        }
        const value = result.value; // Uint8Array
        text += decoder.decode(value, {stream: true});
        // 读取下一个文件片段，重复处理步骤
        return reader.read().then(processData);
      };
      return await reader.read().then(processData);
    }
    args=processHandler(_ajaxProxyInstance.interceptor.request.handler,...args)
    return _ajaxProxyInstance.oriFetch(...args).then(async (response) => {
      let handler=_ajaxProxyInstance.interceptor.response.handler
      if(handler.length>0){
        //默认body都返回json
        let body=await getBody(response.body)
        body=isObjectOrArray(body)?body:toJson(body)
        //axios请求参数---需要重写的参数
        let options={
          url,
          method:req?.method||'GET',
          data:req?.data||{},
          headers:req?.headers||{},
          status: response.status,
          statusText: response.statusText,
          response:body,
          responseHeaders: response.headers||opts.headers,//响应时返回响应header
        }
        // console.log('ajax fetch response----',options.url)
        //重写返回状态与返回文本/json
        for (let i = 0; i < handler.length; ++i) {
          options=handler[i].call(this, options,response,_ajaxProxyInstance.fetch)
        }
        //重新组装成Response
        let streamBody=isObjectOrArray(options.response)?JSON.stringify(options.response):options.response
        const stream = new ReadableStream({
          start(controller) {
            controller.enqueue(new TextEncoder().encode(streamBody));
            controller.close();
          }
        });
        const newResponse = new Response(stream, {
          headers: options.headers||response.headers,
          status: options.status||response.status,
          statusText: options.statusText||response.statusText,
        });
        //生成代理对象
        const responseProxy = new Proxy(newResponse, {
          get: function (target, name) {
            switch (name) {
              case 'body':
              case 'bodyUsed':
              case 'ok':
              case 'redirected':
              case 'type':
              case 'url':
                return response[name];
            }
            return target[name];
          }
        });
        for (let key in responseProxy) {
          if (typeof responseProxy[key] === 'function') {
            responseProxy[key] = responseProxy[key].bind(newResponse);
          }
        }
        return responseProxy;
      }else{
        return response
      }
    })
  }
}

//添加拦截器及监听window message---调用一次
const _initAjaxProxyInstanceInterceptor=()=>{
  window._ajaxProxyInstance=_ajaxProxyInstance
  window._getAjaxList=(str)=>{
    let list=[]
    ajaxList.forEach(r=>{
      if(r.url.indexOf(str)>-1||!str){
        list.push(r)
      }
    })
    return list
  }
  const toJson=(json)=>{return JSON.parse(JSON.stringify(json))}
  let ajaxList=[]//所有ajax请求
  _ajaxProxyInstance.interceptor.response.use((req,response,fetch)=>{
    ajaxList.push(Object.assign({},req))
    return req
  })
  let onRequestFlag=false;
  const onRequest=()=>{
    if(!onRequestFlag){
      _ajaxProxyInstance.interceptor.request.use((req,response,fetch)=>{
        window.postMessage({key:_ajaxProxyInstance.receiveKey,act:'onRequest',params:toJson(req)}, '*')
        return req
      })
      onRequestFlag=true;
    }
  }
  let onResponseFlag=false;
  const onResponse=()=>{
    if(!onRequestFlag){
      _ajaxProxyInstance.interceptor.request.use((req,response,fetch)=>{
        window.postMessage({key:_ajaxProxyInstance.receiveKey,act:'onResponse',params:toJson(req)}, '*')
        return req
      })
      onResponseFlag=true;
    }
  }
  window.addEventListener('message', function (e) {  // 监听 message 事件
    const {origin='*',data={}}=e
    //监听处理ajax
    const {key='',act='getList',params={}}=data;
    if(key==_ajaxProxyInstance.listenerKey){
      switch(act){
        case 'getList':
          window.postMessage({key:_ajaxProxyInstance.receiveKey,act,params:toJson(ajaxList)}, '*')
        break;
        case 'onRequest':
          onRequest()
          break;
        case 'onResponse':
          onResponse()
          break;
        default://可以进行扩展如:扩展通过filter与req来覆盖请求
          break;
      }
    }
  });
}
_initAjaxProxyInstanceInterceptor()
const _initAjaxProxyInstance=()=>{
  for (const k in _ajaxProxyInstance.oriXhr) {
    _ajaxProxyInstance.xhr[k] = _ajaxProxyInstance.oriXhr[k]
  }
  window.XMLHttpRequest = _ajaxProxyInstance.xhr;
  window.fetch = _ajaxProxyInstance.fetch;
}
window.addEventListener("message", function (event) {
  _initAjaxProxyInstance()
}, false);


`

