const fs = require('fs')
const path = require('path')
const util = require('util')
const Resumable = require('./resumable')
const { basename } = require('path')
const { getErrorMessage } = require('./error')

class File {
  constructor ({ filePath, type, size }) {
    this.path = filePath
    this.name = path.basename(filePath)
    this.type = type
    this.size = size
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  slice (start, end, _contentType) {
    return fs.createReadStream(this.path, { start, end })
  }
}

async function uploadFile (token, url, filePath, progress) {
  return new Promise((resolve, reject) => {
    const r = new Resumable({
      target: url,
      headers: {
        authorization: token,
        'x-corellium-image-encoding': 'plain'
      },
      uploadMethod: 'PUT',
      chunkSize: 5 * 1024 * 1024,
      prioritizeFirstAndLastChunk: true,
      method: 'octet'
    })

    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    r.on('fileAdded', (_file) => {
      r.upload()
    })

    r.on('progress', () => {
      if (progress) progress(r.progress())
    })

    r.on('fileError', (_file, message) => {
      reject(message)
    })

    r.on('fileSuccess', (_file, message) => {
      resolve(JSON.parse(message))
    })

    return util
      .promisify(fs.stat)(filePath)
      .then((stat) => {
        const file = new File({
          filePath: filePath,
          type: 'application/octet-stream',
          size: stat.size
        })

        r.addFile(file)
      })
  })
}

async function uploadWithProgress (url, token, file, multi) {
  const fileName = basename(file)

  const bar = multi.newBar(` loading ${fileName} [:bar] :percent`, {
    complete: '=',
    incomplete: ' ',
    width: 30,
    total: 100
  })

  try {
    const res = await uploadFile(
      token,
      url,
      file,
      (progress) => {
        const ticks = Math.ceil(100 * progress)
        bar.tick(ticks)
      }
    )
    return res
  } catch (error) {
    const errorMessage = getErrorMessage(error)
    console.error(`Upload failed: ${errorMessage}`)
  }
}

module.exports = {
  uploadWithProgress
}
