import {
  hasOwn
} from 'uni-shared'

/**
 * 请求任务类
 */
class RequestTask {
  _xhr
  constructor (xhr) {
    this._xhr = xhr
  }

  abort () {
    if (this._xhr) {
      this._xhr.abort()
      delete this._xhr
    }
  }
}

/**
 * 解析响应头
 * @param {string} headers
 * @return {object}
 */
function parseHeaders (headers) {
  var headersObject = {}
  var headersArray = headers.split('\n')
  headersArray.forEach(header => {
    var find = header.match(/(\S+\s*):\s*(.*)/)
    if (!find || find.length !== 3) {
      return
    }
    var key = find[1]
    var val = find[2]
    headersObject[key] = val
  })
  return headersObject
}
/**
 * 发起网络请求
 * @param {object} param0
 * @param {string} callbackId
 * @return {RequestTask}
 */
export function request ({
  url,
  data,
  header,
  method,
  dataType,
  responseType,
  withCredentials
}, callbackId) {
  const {
    invokeCallbackHandler: invoke
  } = UniServiceJSBridge
  var body = null
  var timeout = (__uniConfig.networkTimeout && __uniConfig.networkTimeout.request) || 60 * 1000
  // 根据请求类型处理数据
  var contentType
  for (const key in header) {
    if (hasOwn(header, key)) {
      if (key.toLowerCase() === 'content-type') {
        contentType = header[key]
        if (contentType.indexOf('application/json') === 0) {
          contentType = 'json'
        } else if (contentType.indexOf('application/x-www-form-urlencoded') === 0) {
          contentType = 'urlencoded'
        } else {
          contentType = 'string'
        }
        break
      }
    }
  }
  if (method !== 'GET') {
    if (typeof data === 'string' || data instanceof ArrayBuffer) {
      body = data
    } else {
      if (contentType === 'json') {
        try {
          body = JSON.stringify(data)
        } catch (error) {
          body = data.toString()
        }
      } else if (contentType === 'urlencoded') {
        const bodyArray = []
        for (const key in data) {
          if (hasOwn(data, key)) {
            bodyArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
          }
        }
        body = bodyArray.join('&')
      } else {
        body = data.toString()
      }
    }
  }
  var xhr = new XMLHttpRequest()
  var requestTask = new RequestTask(xhr)
  xhr.open(method, url)
  for (var key in header) {
    if (hasOwn(header, key)) {
      xhr.setRequestHeader(key, header[key])
    }
  }

  var timer = setTimeout(function () {
    xhr.onload = xhr.onabort = xhr.onerror = null
    requestTask.abort()
    invoke(callbackId, {
      errMsg: 'request:fail timeout'
    })
  }, timeout)
  xhr.responseType = responseType
  xhr.onload = function () {
    clearTimeout(timer)
    const statusCode = xhr.status
    let res = responseType === 'text' ? xhr.responseText : xhr.response
    if (responseType === 'text' && dataType === 'json') {
      try {
        res = JSON.parse(res)
      } catch (error) {
        // 和微信一致解析失败不抛出错误
        // invoke(callbackId, {
        //   errMsg: 'request:fail json parse error'
        // })
        // return
      }
    }
    invoke(callbackId, {
      data: res,
      statusCode,
      header: parseHeaders(xhr.getAllResponseHeaders()),
      errMsg: 'request:ok'
    })
  }
  xhr.onabort = function () {
    clearTimeout(timer)
    invoke(callbackId, {
      errMsg: 'request:fail abort'
    })
  }
  xhr.onerror = function () {
    clearTimeout(timer)
    invoke(callbackId, {
      errMsg: 'request:fail'
    })
  }
  xhr.withCredentials = withCredentials
  xhr.send(body)
  return requestTask
}
