import Path from 'path'

export default {
  data() {
    return {
      uploadHelpers: {
        getBooksFromDrop: this.getBooksFromDataTransferItems,
        getBooksFromPicker: this.getBooksFromFileList
      }
    }
  },
  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
    },
    filterAudiobookFiles(files) {
      var validBookFiles = []
      var validOtherFiles = []
      var ignoredFiles = []
      files.forEach((file) => {
        var filetype = this.checkFileType(file.name)
        if (!filetype) ignoredFiles.push(file)
        else {
          file.filetype = filetype
          if (filetype === 'audio' || filetype === 'ebook') validBookFiles.push(file)
          else validOtherFiles.push(file)
        }
      })

      return {
        bookFiles: validBookFiles,
        otherFiles: validOtherFiles,
        ignoredFiles
      }
    },
    audiobookFromItems(items) {
      var { bookFiles, otherFiles, ignoredFiles } = this.filterAudiobookFiles(items)
      if (!bookFiles.length) {
        ignoredFiles = ignoredFiles.concat(otherFiles)
        otherFiles = []
      }
      return [
        {
          bookFiles,
          otherFiles,
          ignoredFiles
        }
      ]
    },
    traverseForAudiobook(folder, depth = 1) {
      if (folder.items.some((f) => f.isDirectory)) {
        var audiobooks = []
        folder.items.forEach((file) => {
          if (file.isDirectory) {
            var audiobookResults = this.traverseForAudiobook(file, ++depth)
            audiobooks = audiobooks.concat(audiobookResults)
          }
        })
        return audiobooks
      } else {
        return this.audiobookFromItems(folder.items)
      }
    },
    fileTreeToAudiobooks(filetree) {
      // 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 audiobookResults = this.traverseForAudiobook({ items: filetree })
        return {
          audiobooks: audiobookResults,
          ignoredFiles: ignoredFilesInRoot
        }
      } else {
        // Single Book drop
        return {
          audiobooks: this.audiobookFromItems(filetree),
          ignoredFiles: []
        }
      }
    },
    getFilesDropped(dataTransferItems) {
      var treemap = {
        path: '/',
        items: []
      }
      function traverseFileTreePromise(item, currtreemap) {
        return new Promise((resolve) => {
          if (item.isFile) {
            item.file((file) => {
              file.filepath = currtreemap.path + file.name //save full path
              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]
            dirReader.readEntries((entries) => {
              let entriesPromises = []
              for (let entr of entries) entriesPromises.push(traverseFileTreePromise(entr, newtreemap))
              resolve(Promise.all(entriesPromises))
            })
          }
        })
      }

      return new Promise((resolve, reject) => {
        let entriesPromises = []
        for (let it of dataTransferItems) {
          var filetree = traverseFileTreePromise(it.webkitGetAsEntry(), treemap)
          entriesPromises.push(filetree)
        }
        Promise.all(entriesPromises).then(() => {
          resolve(treemap.items)
        })
      })
    },
    cleanBook(book, index) {
      var audiobook = {
        index,
        title: '',
        author: '',
        series: '',
        ...book
      }
      var firstBookFile = book.bookFiles[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()
        }
      }
      return audiobook
    },
    async getBooksFromDataTransferItems(items) {
      var files = await this.getFilesDropped(items)
      if (!files || !files.length) return { error: 'No files found ' }
      var audiobooksData = this.fileTreeToAudiobooks(files)
      if (!audiobooksData.audiobooks.length && !audiobooksData.ignoredFiles.length) {
        return { error: 'Invalid file drop' }
      }
      var ignoredFiles = audiobooksData.ignoredFiles
      var index = 1
      var books = audiobooksData.audiobooks.filter((ab) => {
        if (!ab.bookFiles.length) {
          if (ab.otherFiles.length) ignoredFiles = ignoredFiles.concat(ab.otherFiles)
          if (ab.ignoredFiles.length) ignoredFiles = ignoredFiles.concat(ab.ignoredFiles)
        }
        return ab.bookFiles.length
      }).map(ab => this.cleanBook(ab, index++))
      return {
        books,
        ignoredFiles
      }
    },
    getBooksFromFileList(filelist) {
      var ignoredFiles = []
      var otherFiles = []

      var bookMap = {}

      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

          if (filetype === 'audio' || filetype === 'ebook') {
            var dir = file.filepath ? Path.dirname(file.filepath) : ''
            if (!bookMap[dir]) {
              bookMap[dir] = {
                path: dir,
                ignoredFiles: [],
                bookFiles: [],
                otherFiles: []
              }
            }
            bookMap[dir].bookFiles.push(file)
          } else {
            otherFiles.push(file)
          }
        }
      })

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

      var index = 1
      var books = Object.values(bookMap).map(ab => this.cleanBook(ab, index++))
      return {
        books,
        ignoredFiles: ignoredFiles
      }
    },
  }
}