import { isEmptyUtils, isNotEmptyUtils, subString } from './utils'
import fetchQiniu from './fetch-qiniu.js'
import { getQiniuToken1, uploadVideo, uploadImg } from './index'
import fetch from './fetch'

let fileApiUrl = getQiniuToken1()
//该对象有一个 unsubscribe 方法取消订阅，同时终止上传行为。
let subscription = null

//上传返回结果
let result = {
  key: null, //文件保存在空间中的资源名
  path: null, //保存到db的路径(不带域名)
  fullPath: null, //文件网络路径(文件url)
  size: null, //资源尺寸，单位为字节
  name: null, //原始文件名
  ext: null, //上传资源的后缀名，通过自动检测的mimeType 或者原文件的后缀来获取
}

//上传状态
// var status = false;

//FIXME 请注意vue里面不要使用全局变量
let domain = uploadVideo() // 视频

let domain1 = uploadImg() // 图片

let errorCode = new Map([
  [298, '部分操作执行成功'],
  [400, '请求报文格式错误'],
  [401, '认证授权失败'],
  [403, '权限不足，拒绝访问。'],
  [404, '资源不存在'],
  [405, '请求方式错误'],
  [406, '上传的数据 CRC32 校验错误'],
  [413, '请求资源大小大于指定的最大值'],
  [419, '用户账号被冻结'],
  [478, '镜像回源失败'],
  [502, '错误网关'],
  [503, '服务端不可用'],
  [504, '服务端操作超时'],
  [573, '单个资源访问频率过高'],
  [579, '上传成功但是回调失败'],
  [599, '服务端操作失败'],
  [608, '资源内容被修改'],
  [612, '指定资源不存在或已被删除'],
  [614, '目标资源已存在'],
  [630, '已创建的空间数量达到上限，无法创建新空间。'],
  [631, '指定空间不存在'],
  [640, '调用列举资源(list)接口时，指定非法的marker参数。'],
  [701, '在断点续上传过程中，后续上传接收地址不正确或ctx信息已过期。'],
])

let qiniuErrorCheck = function (code, self) {
  errorCode.forEach(function (value, key, map) {
    if (code === key) {
      self.$message.error(value)
      console.error(key + ':' + value)
    }
  })
}

//用来限制上传文件类型，为 null 时表示不对文件类型限制；限制类型放到数组里： ["image/png", "image/jpeg", "image/gif"]
let mimeTypeArray = null

export const createFilePath = (file, fileName) => {
  if (isEmptyUtils(file)) {
    return null
  }
  let arr = fileName.split('_')
  if (arr.length != 4) {
    alert('上传视频文件名格式不正确')
    return null
  }
  let arr4 = arr[3].split('.')

  //文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
  let filePath =
    arr[0] + '/' + arr[1] + '/' + arr[2] + '_' + arr4[0] + '.' + arr4[1]
  console.log(filePath)
  return filePath
}

/**
 * 获取七牛上传凭证
 *
 * @return {Promise} token 七牛上传凭证
 * */
const doQiniuAction1 = (fileType) => {
  console.log('send---' + fileApiUrl)
  return new Promise(function (resolve, reject) {
    // if(isEmptyUtils(localStorage.getItem('qiniuToken'))){
    fetchQiniu(fileApiUrl, { fileType: fileType }, 'GET')
      .then(function (result) {
        let token = null
        if (isNotEmptyUtils(result) && result.code == '000000') {
          token = result.data.qiniuToken
          resolve(token)
          console.log('七牛临时授权成功')
          localStorage.setItem('qiniuToken', token)
        } else {
          reject(result)
          console.error('七牛临时授权失败:', result)
        }
      })
      .catch(function (error) {
        reject()
        console.error('七牛临时授权失败:', error)
      })
    // }else{
    //     console.log('从localStorage获取token:'+localStorage.getItem('qiniuToken'))
    //     resolve(localStorage.getItem('qiniuToken'));
    // }
  })
}

/**
 *
 * @param self
 * @param file
 * @param filePath
 * @param previewId
 * @param progressId
 * @returns {Promise}
 */
export const qiniuUpload = (self, file, filePath, previewId, progressId) => {
  // var deferred = $q.defer();

  return new Promise(function (resolve, reject) {
    if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
      console.error('七牛上传失败:非法参数')
      reject()
    }

    let key = filePath ? filePath : getFilePath(file)

    //修改状态为上传
    self.qiniuUploadStatus = true

    // let token = "BRVB4TpxVFA5Wo6lIpfltmWKOltzGar46tvC3BlR:UHn0LDElwjP4jEZTXdq_1qV6_hw=:eyJzY29wZSI6InBpY2EtdGVzdCIsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiYnVja2V0XCI6XCIkKGJ1Y2tldClcIixcImZzaXplXCI6JChmc2l6ZSksXCJmbmFtZVwiOiQoZm5hbWUpLFwiZXh0XCI6JChleHQpfSIsImRlYWRsaW5lIjoxNTI5NDk0MTc1fQ==";
    doQiniuAction().then(function (token) {
      let putExtra = {
        fname: file.name, //原文件名
        params: {}, //用来放置自定义变量
        mimeType: mimeTypeArray || null, //null || array，用来限制上传文件类型，为 null 时表示不对文件类型限制；限制类型放到数组里： ["image/png", "image/jpeg", "image/gif"]
      }

      let config = {
        useCdnDomain: true, //表示是否使用 cdn 加速域名，为布尔值，true 表示使用，默认为 false。
        region: null, //选择上传域名区域；当为 null 或 undefined 时，自动分析上传域名区域
      }

      /*
       * qiniu.upload 返回一个 observable 对象用来控制上传行为，observable 对像通过 subscribe 方法可以被 observer 所订阅，
       * 订阅同时会开始触发上传，同时返回一个 subscription 对象，该对象有一个 unsubscribe 方法取消订阅，同时终止上传行为。
       * */
      let observable = qiniu.upload(file, key, token, putExtra, config)

      /**
       * 接收上传进度信息，res 参数是一个带有 total 字段的 object，包含loaded、total、percent三个属性，提供上传进
       * total.loaded: number，已上传大小，单位为字节。
       * total.total: number，本次上传的总量控制信息，单位为字节，注意这里的 total 跟文件大小并不一致。
       * total.percent: number，当前上传进度，范围：0～100
       * */
      let next = function (res) {
        //res值{"total":{"loaded":18184,"size":18185,"percent":99.99450096233159}}

        //获取百分比进度
        let progress = res.total.percent.toFixed(2)
        self.uploadProgress = Number(progress)
        console.log('Progress1: ' + progress)
        //如果有进度条
        /*if (isNotEmptyUtils(progressId)) {
                    let obj = $("#" + progressId);
                    //开始上传时,显示进度条
                    if (isNotEmptyUtils(obj.parent())) {
                        //修改状态为上传
                        // status = true;
                        self.qiniuUploadStatus = true;
                        obj.parent().removeClass("hidden");
                        obj.fadeIn("fast");
                    }
                    obj.css("width", progress + '%');
                    obj.text(progress + '%');
                    //上传完成,2秒后淡出进度条
                    if (progress === "100.00") {
                        //修改状态为非上传
                        // status = false;
                        self.qiniuUploadStatus = true;
                        obj.fadeOut(2000);
                    }
                }*/
      }

      /**
       * 接收上传完成后的后端返回信息，res 参数为一个 object， 为上传成功后后端返回的信息
       * ，具体返回结构取决于后端sdk的配置，可参考上传策略(https://developer.qiniu.com/kodo/manual/1206/put-policy)
       * */
      let complete = function (res) {
        console.log('七牛上传完成')
        setTimeout(function () {
          result.key = res.key
          result.path = '/' + res.key
          result.fullPath =
            domain + '/' + res.key + '?v=' + new Date().getTime()
          result.size = res.fsize
          result.name = res.fname
          result.ext = res.ext

          // deferred.resolve(result);
          resolve(result)
          // self.model.qCloudUrl = result.fullPath;
          // $("#introVideoLecture").attr("src", self.model.qCloudUrl);
          //修改状态为非上传
          // status = false;
          self.qiniuUploadStatus = false

          if (isNotEmptyUtils(previewId)) {
            let address = domain + result.path
            console.log('文件路径: ' + address)

            //显示图片
            let $img = $('<img>').attr('src', address)
            let obj = $('#' + previewId)
            obj.empty().append($img)
            obj.css('max-width', '100%')
          }
        }, 2000)
      }

      /**
       * 上传错误后触发，当不是 xhr 请求错误时，会把当前错误产生原因直接抛出，诸如 JSON 解析异常等；当产生 xhr 请求错误时，参数 err 为一个包含 code、message、isRequestError 三个属性的 object：
       * err.isRequestError: 用于区分是否 xhr 请求错误；当 xhr 请求出现错误并且后端通过 HTTP 状态码返回了错误信息时，该参数为 true；否则为 undefined 。
       * err.reqId: string，xhr请求错误的 X-Reqid。
       * err.code: number，请求错误状态码，只有在 err.isRequestError 为 true 的时候才有效，可查阅码值对应说明。
       * err.message: string，错误信息，包含错误码，当后端返回提示信息时也会有相应的错误信息。
       * */
      let error = function (err) {
        //修改状态为非上传
        // status = false;
        self.qiniuUploadStatus = false
        localStorage.removeItem('qiniuToken')
        console.log(
          '七牛上传失败,详细信息请参考:https://developer.qiniu.com/kodo/api/3928/error-responses'
        )
        //输出简略错误信息
        if (err.isRequestError) {
          qiniuErrorCheck(err.code, self)
        } else {
          console.error(err)
        }

        /*modalClick("提示", "上传失败！", "确定", function () {
                    $('#model-modify').modal('hide');
                }, "", null);*/
        // deferred.reject(new Error('七牛上传失败'));
        // return deferred.promise;
        return reject(new Error('七牛上传失败'))
      }

      // 上传开始
      subscription = observable.subscribe(next, error, complete)
    })

    // return deferred.promise;
  })
}

/**
 * 获取时间戳
 * @param {Date} [date]日期对象,为空时,返回当前时间戳
 * @return {String} timeStamp时间戳 格式:yyyyMMddhhmmssS
 */
const timeStamp = (date) => {
  if (isEmptyUtils(date)) {
    return new Date().format('yyyyMMddhhmmssS')
  }

  return date.format('yyyyMMddhhmmssS')
}
/**
 * 获取全局唯一标识符（GUID，Globally Unique Identifier）
 * @return {String} guid
 */
const guid = () => {
  /**
   * @return {String}
   */
  function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
  }

  return (
    S4() +
    S4() +
    '-' +
    S4() +
    '-' +
    S4() +
    '-' +
    S4() +
    '-' +
    S4() +
    S4() +
    S4()
  )
}
/**
 * 文件重命名--七牛图片 2018 11
 * @param {File} [file] 上传文件对象
 * @param {String} [fileName] 指定文件名
 * @param {String} [folder] 指定文件夹
 * @return {String} fileName
 */
export const getFilePath = (file, fileName, folder) => {
  if (isEmptyUtils(file)) {
    return null
  }
  //文件类型
  var ext = file.type
  //后缀名
  var suffix = file.name.substring(file.name.lastIndexOf('.') + 1)
  //若为空则从name中获取---对wps格式的文件获取不到file.type
  if (isEmptyUtils(ext)) {
    ext = suffix
  }
  //获取当前日期对象
  var date = new Date()
  if (isEmptyUtils(fileName)) {
    //重命名后的文件名
    fileName = timeStamp(date) + '-' + subString(guid(), 8) + '.' + suffix
  }

  //文件全路径(文件路径 + 文件名) 扩展名​/年/月/日/
  // var filePath = ext + "/" + date.format('yyyy/MM/dd') + "/" + (isEmptyUtils(folder) ? "" : (folder + "/")) + fileName;
  //var filePath = ext + "/" + "common/" + file.name.split('.')[0] + '-' + timeStamp(date) + "." + suffix;
  var filePath = ext + '/' + 'protal/project/' + timeStamp(date) + '.' + suffix
  console.log('filePath==============', filePath)
  return filePath
}

/**
 *七牛上传图片、视频、文件 2018 11 hws
 * @param self
 * @param file
 * @param filePath
 * @param previewId
 * @param progressId
 * @param fileType 1--图片和文件   空为视频
 * @returns {Promise}
 */
export const doUpload = (
  self,
  file,
  filePath,
  previewId,
  progressId,
  fileType
) => {
  return new Promise(function (resolve, reject) {
    if (isEmptyUtils(file) || isEmptyUtils(filePath)) {
      console.error('七牛上传失败:非法参数')
      reject()
    }
    let key = filePath ? filePath : getFilePath(file)

    //修改状态为上传
    self.qiniuUploadStatus = true
    doQiniuAction1(fileType).then(function (token) {
      let putExtra = {
        fname: file.name, //原文件名
        params: {}, //用来放置自定义变量
        mimeType: mimeTypeArray || null, //null || array，用来限制上传文件类型，为 null 时表示不对文件类型限制；限制类型放到数组里： ["image/png", "image/jpeg", "image/gif"]
      }

      let config = {
        useCdnDomain: true, //表示是否使用 cdn 加速域名，为布尔值，true 表示使用，默认为 false。
        region: null, //选择上传域名区域；当为 null 或 undefined 时，自动分析上传域名区域
      }

      /*
       * qiniu.upload 返回一个 observable 对象用来控制上传行为，observable 对像通过 subscribe 方法可以被 observer 所订阅，
       * 订阅同时会开始触发上传，同时返回一个 subscription 对象，该对象有一个 unsubscribe 方法取消订阅，同时终止上传行为。
       * */
      let observable = qiniu.upload(file, key, token, putExtra, config)

      /**
       * 接收上传进度信息，res 参数是一个带有 total 字段的 object，包含loaded、total、percent三个属性，提供上传进
       * total.loaded: number，已上传大小，单位为字节。
       * total.total: number，本次上传的总量控制信息，单位为字节，注意这里的 total 跟文件大小并不一致。
       * total.percent: number，当前上传进度，范围：0～100
       * */
      let next = function (res) {
        //res值{"total":{"loaded":18184,"size":18185,"percent":99.99450096233159}}

        //获取百分比进度
        let progress = res.total.percent.toFixed(2)
        self.uploadProgress = Number(progress)

        if (progressId == 'uploadProgress1') {
          self.uploadProgress1 = Number(progress)
        }
        if (progressId == 'uploadProgress2') {
          self.uploadProgress2 = Number(progress)
        }
        console.log('Progress2: ' + progress)
      }

      /**
       * 接收上传完成后的后端返回信息，res 参数为一个 object， 为上传成功后后端返回的信息
       * ，具体返回结构取决于后端sdk的配置，可参考上传策略(https://developer.qiniu.com/kodo/manual/1206/put-policy)
       * */
      let complete = function (res) {
        console.log('七牛上传完成')
        setTimeout(function () {
          result.key = res.key
          result.path = '/' + res.key
          if (!fileType) {
            // 图片  文件
            console.log('---domain-------', domain)
            result.fullPath = domain + '/' + res.key
          } else {
            // 视频
            console.log('----domain1------', domain1)
            result.fullPath = domain1 + '/' + res.key
          }
          result.size = res.fsize
          result.name = res.fname
          result.ext = res.ext
          resolve(result)
          self.qiniuUploadStatus = false
        }, 500)
      }

      /**
       * 上传错误后触发，当不是 xhr 请求错误时，会把当前错误产生原因直接抛出，诸如 JSON 解析异常等；当产生 xhr 请求错误时，参数 err 为一个包含 code、message、isRequestError 三个属性的 object：
       * err.isRequestError: 用于区分是否 xhr 请求错误；当 xhr 请求出现错误并且后端通过 HTTP 状态码返回了错误信息时，该参数为 true；否则为 undefined 。
       * err.reqId: string，xhr请求错误的 X-Reqid。
       * err.code: number，请求错误状态码，只有在 err.isRequestError 为 true 的时候才有效，可查阅码值对应说明。
       * err.message: string，错误信息，包含错误码，当后端返回提示信息时也会有相应的错误信息。
       * */
      let error = function (err) {
        //修改状态为非上传
        // status = false;
        self.qiniuUploadStatus = false
        localStorage.removeItem('qiniuToken')
        console.log(
          '七牛上传失败,详细信息请参考:https://developer.qiniu.com/kodo/api/3928/error-responses'
        )
        //输出简略错误信息
        if (err.isRequestError) {
          qiniuErrorCheck(err.code, self)
        } else {
          console.error(err)
        }
        return reject(new Error('七牛上传失败'))
      }

      // 上传开始
      subscription = observable.subscribe(next, error, complete)
    })
    // 保存到全局对象
    window.QNSubscription = subscription
  })
}
// 取消上传
export const unsubscribe = () => {
  subscription.unsubscribe()
}
