import Path from 'path'

export default {
  data() {
    return {
      uploadHelpers: {
        getItemsFromDrop: this.getItemsFromDataTransferItems,
        getItemsFromPicker: this.getItemsFromFilelist
      }
    }
  },
  methods: {
    checkFileType(filename) {
      var ext = Path.extname(filename)
      if (!ext) return false
      if (ext.startsWith('.')) ext = ext.slice(1)
      ext = ext.toLowerCase()

      for (const filetype in this.$constants.SupportedFileTypes) {
        if (this.$constants.SupportedFileTypes[filetype].includes(ext)) {
          return filetype
        }
      }
      return false
    },
    filterItemFiles(files, mediaType) {
      var validItemFiles = []
      var validOtherFiles = []
      var ignoredFiles = []
      files.forEach((file) => {
        // var filetype = this.checkFileType(file.name)
        if (!file.filetype) ignoredFiles.push(file)
        else {
          // file.filetype = filetype
          if (file.filetype === 'audio' || (file.filetype === 'ebook' && mediaType === 'book')) validItemFiles.push(file)
          else validOtherFiles.push(file)
        }
      })

      return {
        itemFiles: validItemFiles,
        otherFiles: validOtherFiles,
        ignoredFiles
      }
    },
    itemFromTreeItems(items, mediaType) {
      var { itemFiles, otherFiles, ignoredFiles } = this.filterItemFiles(items, mediaType)
      if (!itemFiles.length) {
        ignoredFiles = ignoredFiles.concat(otherFiles)
        otherFiles = []
      }
      return [
        {
          itemFiles,
          otherFiles,
          ignoredFiles
        }
      ]
    },
    traverseForItem(folder, mediaType, depth = 1) {
      if (folder.items.some((f) => f.isDirectory)) {
        var items = []
        folder.items.forEach((file) => {
          if (file.isDirectory) {
            var itemResults = this.traverseForItem(file, mediaType, ++depth)
            items = items.concat(itemResults)
          }
        })
        return items
      } else {
        return this.itemFromTreeItems(folder.items, mediaType)
      }
    },
    fileTreeToItems(filetree, mediaType) {
      // Has directores - Is Multi Book Drop
      if (filetree.some((f) => f.isDirectory)) {
        var ignoredFilesInRoot = filetree.filter((f) => !f.isDirectory)
        if (ignoredFilesInRoot.length) filetree = filetree.filter((f) => f.isDirectory)

        var itemResults = this.traverseForItem({ items: filetree }, mediaType)
        return {
          items: itemResults,
          ignoredFiles: ignoredFilesInRoot
        }
      } else if (filetree.some((f) => f.filetype !== 'audio') || mediaType !== 'book') {
        // Single Book drop
        return {
          items: this.itemFromTreeItems(filetree, mediaType),
          ignoredFiles: []
        }
      } else {
        // Only audio files dropped so treat each one as an audiobook
        return {
          items: filetree.map((audioFile) => ({ itemFiles: [audioFile], otherFiles: [], ignoredFiles: [] })),
          ignoredFiles: []
        }
      }
    },
    getFilesDropped(dataTransferItems) {
      var treemap = {
        path: '/',
        items: []
      }
      function traverseFileTreePromise(item, currtreemap, checkFileType) {
        return new Promise((resolve) => {
          if (item.isFile) {
            item.file((file) => {
              file.filepath = currtreemap.path + file.name //save full path
              file.filetype = checkFileType(file.name)
              currtreemap.items.push(file)
              resolve(file)
            })
          } else if (item.isDirectory) {
            let dirReader = item.createReader()
            currtreemap.items.push({
              isDirectory: true,
              dirname: item.name,
              path: currtreemap.path + item.name + '/',
              items: []
            })
            var newtreemap = currtreemap.items[currtreemap.items.length - 1]

            let entriesPromises = []
            // readEntries returns 100 items max, continue calling readEntries until empty
            function readEntries() {
              dirReader.readEntries((entries) => {
                if (entries.length > 0) {
                  for (let entr of entries) {
                    entriesPromises.push(traverseFileTreePromise(entr, newtreemap, checkFileType))
                  }
                  readEntries()
                } else {
                  resolve(Promise.all(entriesPromises))
                }
              })
            }
            readEntries()
          }
        })
      }

      return new Promise((resolve, reject) => {
        let entriesPromises = []
        for (let it of dataTransferItems) {
          var filetree = traverseFileTreePromise(it.webkitGetAsEntry(), treemap, this.checkFileType)
          entriesPromises.push(filetree)
        }
        Promise.all(entriesPromises).then(() => {
          resolve(treemap.items)
        })
      })
    },
    cleanBook(book, index) {
      var audiobook = {
        index,
        title: '',
        author: '',
        series: '',
        ...book
      }
      var firstBookFile = book.itemFiles[0]
      if (!firstBookFile.filepath) {
        return audiobook // No path
      }

      var firstBookPath = Path.dirname(firstBookFile.filepath)

      var dirs = firstBookPath.split('/').filter(d => !!d && d !== '.')
      if (dirs.length) {
        audiobook.title = dirs.pop()
        if (dirs.length > 1) {
          audiobook.series = dirs.pop()
        }
        if (dirs.length) {
          audiobook.author = dirs.pop()
        }
      } else {
        // Use file basename as title
        audiobook.title = Path.basename(firstBookFile.name, Path.extname(firstBookFile.name))
      }
      return audiobook
    },
    cleanPodcast(item, index) {
      var podcast = {
        index,
        title: '',
        ...item
      }
      var firstAudioFile = podcast.itemFiles[0]
      if (!firstAudioFile.filepath) return podcast // No path
      var firstPath = Path.dirname(firstAudioFile.filepath)
      var dirs = firstPath.split('/').filter(d => !!d && d !== '.')
      if (dirs.length) {
        podcast.title = dirs.length > 1 ? dirs[1] : dirs[0]
      } else {
        podcast.title = Path.basename(firstAudioFile.name, Path.extname(firstAudioFile.name))
      }

      return podcast
    },
    cleanItem(item, mediaType, index) {
      if (mediaType === 'podcast') return this.cleanPodcast(item, index)
      return this.cleanBook(item, index)
    },
    async getItemsFromDataTransferItems(dataTransferItems, mediaType) {
      var files = await this.getFilesDropped(dataTransferItems)
      if (!files || !files.length) return { error: 'No files found ' }

      var itemData = this.fileTreeToItems(files, mediaType)
      if (!itemData.items.length && !itemData.ignoredFiles.length) {
        return { error: 'Invalid file drop' }
      }
      var ignoredFiles = itemData.ignoredFiles
      var index = 1
      var items = itemData.items.filter((ab) => {
        if (!ab.itemFiles.length) {
          if (ab.otherFiles.length) ignoredFiles = ignoredFiles.concat(ab.otherFiles)
          if (ab.ignoredFiles.length) ignoredFiles = ignoredFiles.concat(ab.ignoredFiles)
        }
        return ab.itemFiles.length
      }).map(ab => this.cleanItem(ab, mediaType, index++))
      return {
        items,
        ignoredFiles
      }
    },
    getItemsFromFilelist(filelist, mediaType) {
      var ignoredFiles = []
      var otherFiles = []

      var itemMap = {}

      filelist.forEach((file) => {
        var filetype = this.checkFileType(file.name)
        if (!filetype) ignoredFiles.push(file)
        else {
          file.filetype = filetype
          if (file.webkitRelativePath) file.filepath = file.webkitRelativePath
          else file.filepath = file.name

          if (filetype === 'audio' || (filetype === 'ebook' && mediaType === 'book')) {
            var dir = file.filepath ? Path.dirname(file.filepath) : ''
            if (dir === '.') dir = ''

            if (!itemMap[dir]) {
              itemMap[dir] = {
                path: dir,
                ignoredFiles: [],
                itemFiles: [],
                otherFiles: []
              }
            }
            itemMap[dir].itemFiles.push(file)
          } else {
            otherFiles.push(file)
          }
        }
      })

      otherFiles.forEach((file) => {
        var dir = Path.dirname(file.filepath)
        var findItem = Object.values(itemMap).find(b => dir.startsWith(b.path))
        if (findItem) {
          findItem.otherFiles.push(file)
        } else {
          ignoredFiles.push(file)
        }
      })

      var items = []
      var index = 1
      // If book media type and all files are audio files then treat each one as an audiobook
      if (itemMap[''] && !otherFiles.length && mediaType === 'book' && !itemMap[''].itemFiles.some(f => f.filetype !== 'audio')) {
        items = itemMap[''].itemFiles.map((audioFile) => {
          return this.cleanItem({ itemFiles: [audioFile], otherFiles: [], ignoredFiles: [] }, mediaType, index++)
        })
      } else {
        items = Object.values(itemMap).map(i => this.cleanItem(i, mediaType, index++))
      }

      return {
        items,
        ignoredFiles: ignoredFiles
      }
    },
  }
}