import download from '../../utils/download'
import fs from 'fs'
import path from 'path'
import music from '../../utils/music'
import { getMusicType } from '../../utils/music/utils'
import {
  setMeta,
  saveLrc,
  getLyric as getLyricFromStorage,
  setLyric,
  getMusicUrl as getMusicUrlFormStorage,
  setMusicUrl,
  assertApiSupport,
  filterFileName,
} from '../../utils'
import { NAMES, rendererInvoke } from '@common/ipc'
import { initDownloadList, downloadList, downloadListMap, downloadStatus } from '@renderer/core/share/download'
import { markRaw } from '@renderer/utils/vueTools'
import { download as eventDownloadNames } from '@renderer/event/names'

window.downloadList = []
window.downloadListFull = []
window.downloadListFullMap = new Map()
// state
const state = {
  // list: window.downloadList,
  // downloadStatus: {
  //   RUN: 'run',
  //   WAITING: 'waiting',
  //   PAUSE: 'pause',
  //   ERROR: 'error',
  //   COMPLETED: 'completed',
  // },
}


const dls = {}
const tryNum = {}


// getters
const getters = {
  // list: state => downloadList || [],
  // downloadStatus: state => downloadStatus,
}

const checkPath = path => new Promise((resolve, reject) => {
  fs.access(path, fs.constants.F_OK | fs.constants.W_OK, err => {
    if (err) {
      if (err.code === 'ENOENT') {
        fs.mkdir(path, { recursive: true }, err => {
          if (err) return reject(err)
          resolve()
        })
        return
      }
      return reject(err)
    }
    resolve()
  })
})

const getExt = type => {
  switch (type) {
    case '128k':
    case '192k':
    case '320k':
      return 'mp3'
    case 'ape':
      return 'ape'
    case 'flac':
      return 'flac'
    case 'wav':
      return 'wav'
  }
}

const checkList = (list, musicInfo, type, ext) => list.some(s => s.songmid === musicInfo.songmid && (s.metadata.type === type || s.metadata.ext === ext))

const getStartTask = (list, downloadStatus, maxDownloadNum) => {
  let downloadCount = 0
  const waitList = list.filter(item => item.status == downloadStatus.WAITING ? true : (item.status === downloadStatus.RUN && ++downloadCount && false))
  // console.log(downloadCount, waitList)
  return downloadCount < maxDownloadNum ? waitList.shift() || null : false
}

const handleGetMusicUrl = function(musicInfo, type, retryedSource = [], originMusic) {
  // console.log(musicInfo.source)
  if (!originMusic) originMusic = musicInfo
  let reqPromise
  try {
    reqPromise = music[musicInfo.source].getMusicUrl(musicInfo, type).promise
  } catch (err) {
    reqPromise = Promise.reject(err)
  }
  return reqPromise.catch(err => {
    if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
    return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
      console.log('find otherSource', otherSource)
      if (otherSource.length) {
        for (const item of otherSource) {
          if (retryedSource.includes(item.source) || !assertApiSupport(item.source)) continue
          console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
          return handleGetMusicUrl.call(this, item, type, retryedSource, originMusic)
        }
      }
      return Promise.reject(err)
    })
  })
}

const getMusicUrl = async function(downloadInfo, isUseOtherSource, isRefresh) {
  const cachedUrl = await getMusicUrlFormStorage(downloadInfo.metadata.musicInfo, downloadInfo.metadata.type)
  if (!downloadInfo.metadata.musicInfo._types[downloadInfo.metadata.type]) {
    // 兼容旧版酷我源搜索列表过滤128k音质的bug
    if (!(downloadInfo.metadata.musicInfo.source == 'kw' && downloadInfo.metadata.type == '128k')) throw new Error('该歌曲没有可下载的音频')

    // return Promise.reject(new Error('该歌曲没有可下载的音频'))
  }
  return cachedUrl && !isRefresh
    ? cachedUrl
    : (
        isUseOtherSource
          ? handleGetMusicUrl.call(this, downloadInfo.metadata.musicInfo, downloadInfo.metadata.type)
          : music[downloadInfo.metadata.musicInfo.source].getMusicUrl(downloadInfo.metadata.musicInfo, downloadInfo.metadata.type).promise
      ).then(({ url }) => {
        setMusicUrl(downloadInfo.metadata.musicInfo, downloadInfo.metadata.type, url)
        return url
      })
}
const getPic = function(musicInfo, retryedSource = [], originMusic) {
  // console.log(musicInfo.source)
  if (!originMusic) originMusic = musicInfo
  let reqPromise
  try {
    reqPromise = music[musicInfo.source].getPic(musicInfo).promise
  } catch (err) {
    reqPromise = Promise.reject(err)
  }
  return reqPromise.catch(err => {
    if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
    return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
      console.log('find otherSource', otherSource)
      if (otherSource.length) {
        for (const item of otherSource) {
          if (retryedSource.includes(item.source)) continue
          console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
          return getPic.call(this, item, retryedSource, originMusic)
        }
      }
      return Promise.reject(err)
    })
  })
}

const handleGetLyric = function(musicInfo, retryedSource = [], originMusic) {
  if (!originMusic) originMusic = musicInfo
  let reqPromise
  try {
    reqPromise = music[musicInfo.source].getLyric(musicInfo).promise
  } catch (err) {
    reqPromise = Promise.reject(err)
  }
  return reqPromise.catch(err => {
    if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source)
    return this.dispatch('list/getOtherSource', originMusic).then(otherSource => {
      console.log('find otherSource', otherSource)
      if (otherSource.length) {
        for (const item of otherSource) {
          if (retryedSource.includes(item.source)) continue
          console.log('try toggle to: ', item.source, item.name, item.singer, item.interval)
          return getLyric.call(this, item, retryedSource, originMusic)
        }
      }
      return Promise.reject(err)
    })
  })
}

const getLyric = function(musicInfo, isUseOtherSource) {
  return getLyricFromStorage(musicInfo).then(lrcInfo => {
    return (
      lrcInfo.lyric
        ? Promise.resolve({ lyric: lrcInfo.lyric, tlyric: lrcInfo.tlyric || '' })
        : (
            isUseOtherSource
              ? handleGetLyric.call(this, musicInfo)
              : music[musicInfo.source].getLyric(musicInfo).promise
          ).then(({ lyric, tlyric, lxlyric }) => {
            setLyric(musicInfo, { lyric, tlyric, lxlyric })
            return { lyric, tlyric, lxlyric }
          }).catch(err => {
            console.log(err)
            return null
          })
    ).then(lrcs => {
      if (!lrcs) return lrcs
      if (global.i18n.locale != 'zh-tw') return lrcs
      return rendererInvoke(NAMES.mainWindow.lang_s2t, Buffer.from(lrcs.lyric).toString('base64')).then(b64 => Buffer.from(b64, 'base64').toString()).then(lyric => {
        lrcs.lyric = lyric
        return lrcs
      })
    })
  })
}

// 修复 1.1.x版本 酷狗源歌词格式
const fixKgLyric = lrc => /\[00:\d\d:\d\d.\d+\]/.test(lrc) ? lrc.replace(/(?:\[00:(\d\d:\d\d.\d+\]))/gm, '[$1') : lrc

/**
 * 设置歌曲meta信息
 * @param {*} downloadInfo
 * @param {*} filePath
 * @param {*} isEmbedPic // 是否嵌入图片
 */
const saveMeta = function(downloadInfo, filePath, isUseOtherSource, isEmbedPic, isEmbedLyric) {
  if (downloadInfo.metadata.type === 'ape') return
  const tasks = [
    isEmbedPic
      ? downloadInfo.metadata.musicInfo.img
        ? Promise.resolve(downloadInfo.metadata.musicInfo.img)
        : (
            isUseOtherSource
              ? getPic.call(this, downloadInfo.metadata.musicInfo)
              : music[downloadInfo.metadata.musicInfo.source].getPic(downloadInfo.metadata.musicInfo).promise
          ).catch(err => {
            console.log(err)
            return null
          })
      : Promise.resolve(),
    isEmbedLyric
      ? getLyric.call(this, downloadInfo.metadata.musicInfo, isUseOtherSource)
      : Promise.resolve(),
  ]
  Promise.all(tasks).then(([imgUrl, lyrics = {}]) => {
    if (lyrics.lyric) lyrics.lyric = fixKgLyric(lyrics.lyric)
    setMeta(filePath, {
      title: downloadInfo.metadata.musicInfo.name,
      artist: downloadInfo.metadata.musicInfo.singer,
      album: downloadInfo.metadata.musicInfo.albumName,
      APIC: imgUrl,
      lyrics: lyrics.lyric,
    })
  })
}

/**
 * 保存歌词
 * @param {*} downloadInfo
 * @param {*} filePath
 */
const downloadLyric = function(downloadInfo, isUseOtherSource, filePath, lrcFormat) {
  getLyric.call(this, downloadInfo.metadata.musicInfo, isUseOtherSource).then(lrcs => {
    if (lrcs?.lyric) {
      lrcs.lyric = fixKgLyric(lrcs.lyric)
      saveLrc(filePath.replace(/(mp3|flac|ape|wav)$/, 'lrc'), lrcs.lyric, lrcFormat)
    }
  })
}

const refreshUrl = function(commit, downloadInfo, isUseOtherSource) {
  commit('setStatusText', { downloadInfo, text: '链接失效，正在刷新链接' })
  getMusicUrl.call(this, downloadInfo, isUseOtherSource, true).then(url => {
    commit('updateUrl', { downloadInfo, url })
    commit('setStatusText', { downloadInfo, text: '链接刷新成功' })
    const dl = dls[downloadInfo.key]
    if (!dl) return
    dl.refreshUrl(url)
    dl.start().catch(err => {
      commit('onError', { downloadInfo, errorMsg: err.message })
      commit('setStatusText', { downloadInfo, text: err.message })
      this.dispatch('download/startTask')
    })
  }).catch(err => {
    // console.log(err)
    commit('onError', { downloadInfo, errorMsg: err.message })
    commit('setStatusText', { downloadInfo, text: err.message })
    this.dispatch('download/startTask')
  })
}

/**
 * 删除文件
 * @param {*} path
 */
const deleteFile = path => new Promise((resolve, reject) => {
  fs.access(path, fs.constants.F_OK, err => {
    if (err) return err.code == 'ENOENT' ? resolve() : reject(err)
    fs.unlink(path, err => {
      if (err) return reject(err)
      resolve()
    })
  })
})

const createDownloadInfo = ({ musicInfo, type, list, fileName, savePath }) => {
  type = getMusicType(musicInfo, type)
  let ext = getExt(type)
  const key = `${musicInfo.songmid}${ext}`
  if (checkList(list, musicInfo, type, ext)) return null
  const downloadInfo = {
    isComplate: false,
    status: downloadStatus.WAITING,
    statusText: '待下载',
    songmid: musicInfo.songmid,
    progress: {
      downloaded: 0,
      total: 0,
      progress: 0,
    },
    name: `${musicInfo.name} - ${musicInfo.singer}`,
    key,
    metadata: {
      musicInfo,
      url: null,
      type,
      ext,
      fileName: filterFileName(`${fileName
        .replace('歌名', musicInfo.name)
        .replace('歌手', musicInfo.singer)}.${ext}`),
    },
  }
  downloadInfo.metadata.filePath = path.join(savePath, downloadInfo.metadata.fileName)
  // commit('addTask', downloadInfo)

  // 删除同路径下的同名文件
  deleteFile(downloadInfo.metadata.filePath)
  // .catch(err => {
  //   if (err.code !== 'ENOENT') return commit('setStatusText', { downloadInfo, text: '文件删除失败' })
  // })

  if (dls[downloadInfo.key]) {
    const dl = dls[downloadInfo.key]
    delete dls[downloadInfo.key]
    dl.stop()
  }

  return downloadInfo
}

// let waitingUpdateTasks = {}
// const delayUpdateProgress = throttle(function(commit) {
//   commit('setProgressDelay')
// }, 1000)


// actions
const actions = {
  async createDownload({ state, rootState, commit, dispatch }, { musicInfo, type }) {
    const downloadInfo = createDownloadInfo({
      musicInfo,
      type,
      fileName: rootState.setting.download.fileName,
      savePath: rootState.setting.download.savePath,
      list: downloadList,
    })
    if (!downloadInfo) return
    commit('addTask', { downloadInfo, addMusicLocationType: rootState.setting.list.addMusicLocationType })
    let result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    console.log(result)
    while (result) {
      dispatch('startTask', result)
      result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    }
  },
  createDownloadMultiple({ state, rootState, commit, dispatch }, { list, type }) {
    if (!list.length) return
    const taskList = list.map(musicInfo => {
      return createDownloadInfo({
        musicInfo,
        type,
        fileName: rootState.setting.download.fileName,
        savePath: rootState.setting.download.savePath,
        list: downloadList,
      })
    }).filter(task => task)
    commit('addTasks', { list: taskList, addMusicLocationType: rootState.setting.list.addMusicLocationType })
    let result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    while (result) {
      dispatch('startTask', result)
      result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    }
  },
  async handleStartTask({ commit, dispatch, rootState }, downloadInfo) {
    // 开始任务
    commit('onStart', downloadInfo)
    commit('setStatusText', { downloadInfo, text: '任务初始化中' })
    try {
      await checkPath(rootState.setting.download.savePath)
    } catch (error) {
      commit('onError', { downloadInfo, errorMsg: error.message })
      commit('setStatusText', { downloadInfo, text: '检查下载目录出错: ' + error.message })
      await dispatch('startTask')
      return
    }
    const _this = this
    const options = {
      url: downloadInfo.metadata.url,
      path: rootState.setting.download.savePath,
      fileName: downloadInfo.metadata.fileName,
      method: 'get',
      override: true,
      onCompleted() {
        // if (downloadInfo.progress.progress != '100.00') {
        //   delete dls[downloadInfo.key]
        //   return dispatch('startTask', downloadInfo)
        // }
        commit('onCompleted', downloadInfo)
        dispatch('startTask')

        saveMeta.call(_this, downloadInfo, downloadInfo.metadata.filePath, rootState.setting.download.isUseOtherSource, rootState.setting.download.isEmbedPic, rootState.setting.download.isEmbedLyric)
        if (rootState.setting.download.isDownloadLrc) downloadLyric.call(_this, downloadInfo, rootState.setting.download.isUseOtherSource, downloadInfo.metadata.filePath, rootState.setting.download.lrcFormat)
        console.log('on complate')
      },
      onError(err) {
        console.log(err)
        if (err.code == 'EPERM') {
          commit('onError', { downloadInfo, errorMsg: '歌曲保存位置被占用或没有写入权限，请尝试更改歌曲保存目录或重启软件或重启电脑，错误详情：' + err.message })
          return
        }
        // console.log(tryNum[downloadInfo.key])
        if (++tryNum[downloadInfo.key] > 2) {
          commit('onError', { downloadInfo, errorMsg: err.message })
          dispatch('startTask')
          return
        }
        if (err.code == 'ENOTFOUND') {
          commit('onError', { downloadInfo, errorMsg: '链接失效' })
          refreshUrl.call(_this, commit, downloadInfo, rootState.setting.download.isUseOtherSource)
        } else {
          console.log('Download failed, Attempting Retry')
          dls[downloadInfo.key].start()
          commit('setStatusText', { downloadInfo, text: '正在重试' })
        }
      },
      onFail(response) {
        if (++tryNum[downloadInfo.key] > 2) {
          commit('onError', { downloadInfo, errorMsg: '下载失败' })
          dispatch('startTask')
          return
        }
        switch (response.statusCode) {
          case 401:
          case 403:
          case 410:
            commit('onError', { downloadInfo, errorMsg: '链接失效' })
            refreshUrl.call(_this, commit, downloadInfo, rootState.setting.download.isUseOtherSource)
            break
          default:
            dls[downloadInfo.key].start()
            commit('setStatusText', { downloadInfo, text: '正在重试' })
            break
        }
      },
      onStart() {
        commit('onStart', downloadInfo)
        console.log('on start')
      },
      onProgress(status) {
        commit('onProgress', { downloadInfo, status })
        console.log(status)
      },
      onStop() {
        commit('pauseTask', downloadInfo)
        dispatch('startTask')
      },
    }
    commit('setStatusText', { downloadInfo, text: '获取URL中...' })
    let p = options.url
      ? Promise.resolve()
      : getMusicUrl.call(this, downloadInfo, rootState.setting.download.isUseOtherSource).then(url => {
        commit('updateUrl', { downloadInfo, url })
        if (!url) return Promise.reject(new Error('获取URL失败'))
        options.url = url
      })
    p.then(() => {
      tryNum[downloadInfo.key] = 0
      dls[downloadInfo.key] = download(options)
    }).catch(err => {
      // console.log(err.message)
      commit('onError', { downloadInfo, errorMsg: err.message })
      commit('setStatusText', { downloadInfo, text: err.message })
      dispatch('startTask')
    })
  },
  async removeTask({ commit, state, dispatch }, item) {
    if (dls[item.key]) {
      if (item.status == downloadStatus.RUN) {
        try {
          await dls[item.key].stop()
        } catch (_) {}
      }
      delete dls[item.key]
    }
    commit('removeTask', item)
    if (item.status != downloadStatus.COMPLETED) {
      try {
        await deleteFile(item.metadata.filePath)
      } catch (_) {}
    }
    switch (item.status) {
      case downloadStatus.RUN:
      case downloadStatus.WAITING:
        await dispatch('startTask')
    }
  },
  removeTasks({ rootState, commit, dispatch }, list) {
    for (const item of list) {
      if (dls[item.key]) {
        if (item.status == downloadStatus.RUN) {
          dls[item.key].stop().finally(() => {
            delete dls[item.key]
          })
        } else {
          delete dls[item.key]
        }
      }
      if (item.status != downloadStatus.COMPLETED) {
        deleteFile(item.metadata.filePath).catch(_ => _)
      }
    }
    commit('removeTasks', list)
    let result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    while (result) {
      dispatch('startTask', result)
      result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    }
  },
  async startTask({ state, rootState, commit, dispatch }, downloadInfo) {
    // 检查是否可以开始任务
    if (downloadInfo && !downloadInfo.isComplate && downloadInfo.status != downloadStatus.RUN) {
      const result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
      if (result === false) {
        commit('setStatus', { downloadInfo, status: downloadStatus.WAITING })
        return
      }
    } else {
      const result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
      if (!result) return
      downloadInfo = result
    }

    let dl = dls[downloadInfo.key]
    if (dl) {
      commit('updateFilePath', {
        downloadInfo,
        filePath: path.join(rootState.setting.download.savePath, downloadInfo.metadata.fileName),
      })
      dl.updateSaveInfo(rootState.setting.download.savePath, downloadInfo.metadata.fileName)
      try {
        await dl.start()
      } catch (error) {
        commit('onError', { downloadInfo, errorMsg: error.message })
        commit('setStatusText', error.message)
        await dispatch('startTask')
      }
    } else {
      await dispatch('handleStartTask', downloadInfo)
    }
  },
  startTasks({ commit, rootState, dispatch }, list) {
    list = list.filter(item => !(item.isComplate || item.status == downloadStatus.RUN || item.status == downloadStatus.WAITING))
    commit('setStatus', { list, status: downloadStatus.WAITING })
    let result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    while (result) {
      dispatch('startTask', result)
      result = getStartTask(downloadList, downloadStatus, rootState.setting.download.maxDownloadNum)
    }
  },
  async pauseTask({ commit }, item) {
    if (item.isComplate) return
    let dl = dls[item.key]
    if (dl) dl.stop()
    commit('setStatus', { downloadInfo: item, status: downloadStatus.PAUSE })
  },
  pauseTasks({ commit, rootState, dispatch }, list) {
    const waitingTasks = list.filter(item => item.status == downloadStatus.WAITING)
    commit('setStatus', { list: waitingTasks, status: downloadStatus.PAUSE })
    const runningTasks = list.filter(item => item.status == downloadStatus.RUN)
    for (const item of runningTasks) {
      if (item.isComplate) return
      let dl = dls[item.key]
      if (dl) dl.stop()
    }
    commit('setStatus', { list: runningTasks, status: downloadStatus.PAUSE })
  },
}

// mitations
const mutations = {
  addTask(state, { downloadInfo, addMusicLocationType }) {
    downloadListMap.set(downloadInfo.key, downloadInfo)
    switch (addMusicLocationType) {
      case 'top':
        downloadList.unshift(downloadInfo)
        break
      case 'bottom':
      default:
        downloadList.push(downloadInfo)
        break
    }
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  addTasks(state, { list, addMusicLocationType }) {
    let newList
    const map = {}
    const fullMap = {}
    const ids = []
    switch (addMusicLocationType) {
      case 'top':
        newList = [...list, ...downloadList]
        for (let i = newList.length - 1; i > -1; i--) {
          const item = newList[i]
          if (map[item.key]) continue
          ids.unshift(item.key)
          map[item.key] = item
          fullMap[item.key] = newList[i]
        }
        break
      case 'bottom':
      default:
        newList = [...downloadList, ...list]
        newList.forEach((item, index) => {
          if (map[item.key]) return
          ids.push(item.key)
          map[item.key] = item
          fullMap[item.key] = newList[index]
        })
        break
    }
    initDownloadList(ids.map(id => map[id]))
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  removeTask(state, downloadInfo) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadListMap.delete(downloadInfo.key)
    downloadList.splice(index, 1)
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  removeTasks(state, list) {
    let set = new Set()
    let ids = []
    for (const item of downloadList) {
      ids.push(item.key)
      set.add(item.key)
    }
    for (const { key } of list) {
      if (set.has(key)) delete set.delete(key)
    }
    let newList = []
    for (const id of ids) {
      if (set.has(id)) {
        newList.push(downloadListMap.get(id))
      }
    }
    initDownloadList(newList)
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  pauseTask(state, downloadInfo) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.status = downloadStatus.PAUSE
    downloadInfo.statusText = '暂停下载'
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  setStatusText(state, { downloadInfo, index, text }) { // 设置状态文本
    if (downloadInfo) {
      index = downloadList.findIndex(m => m.key == downloadInfo.key)
    }
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.statusText = text
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  setStatus(state, { downloadInfo, index, status, list }) { // 设置状态及状态文本
    let text
    switch (status) {
      case downloadStatus.RUN:
        text = '正在下载'
        break
      case downloadStatus.WAITING:
        text = '等待下载'
        break
      case downloadStatus.PAUSE:
        text = '暂停下载'
        break
      case downloadStatus.ERROR:
        text = '任务出错'
        break
      case downloadStatus.COMPLETED:
        text = '下载完成'
        break
    }
    if (list) {
      for (let downloadInfo of list) {
        const index = downloadList.findIndex(m => m.key == downloadInfo.key)
        if (index < 0) return
        downloadInfo = downloadList[index]
        downloadInfo.statusText = text
        downloadInfo.status = status
      }
    } else {
      if (downloadInfo) {
        index = downloadList.findIndex(m => m.key == downloadInfo.key)
      }
      if (index < 0) return
      downloadInfo = downloadList[index]
      downloadInfo.statusText = text
      downloadInfo.status = status
    }
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  onCompleted(state, downloadInfo) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    // console.log(index)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.isComplate = true
    downloadInfo.status = downloadStatus.COMPLETED
    downloadInfo.statusText = '下载完成'
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  onError(state, { downloadInfo, errorMsg }) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.status = downloadStatus.ERROR
    downloadInfo.statusText = errorMsg || '任务出错'
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  onStart(state, downloadInfo) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.status = downloadStatus.RUN
    downloadInfo.statusText = '正在下载'
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  onProgress(state, { downloadInfo, status }) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.progress.progress = status.progress
    downloadInfo.progress.downloaded = status.downloaded
    downloadInfo.progress.total = status.total
  },
  initDownloadList(state, list) {
    for (const task of list) {
      markRaw(task.metadata)
    }
    initDownloadList(list)
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  updateUrl(state, { downloadInfo, url }) {
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.metadata.url = url
    window.eventHub.emit(eventDownloadNames.listChange)
  },
  updateFilePath(state, { downloadInfo, filePath }) {
    if (downloadInfo.metadata.filePath === filePath) return
    const index = downloadList.findIndex(m => m.key == downloadInfo.key)
    if (index < 0) return
    downloadInfo = downloadList[index]
    downloadInfo.metadata.filePath = filePath
    window.eventHub.emit(eventDownloadNames.listChange)
  },
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations,
}
