function isImageFile(file) {
  return file && file.type && file.type.indexOf('image/') === 0
}

function canvasToBlob(canvas, type, quality) {
  return new Promise(resolve => {
    if (!canvas.toBlob) {
      resolve(null)
      return
    }
    canvas.toBlob(blob => resolve(blob), type, quality)
  })
}

function loadImage(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = event => {
      const image = new Image()
      image.onload = () => resolve(image)
      image.onerror = reject
      image.src = event.target.result
    }
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

export async function compressImageForUpload(file, options = {}) {
  const maxSize = options.maxSize || 3 * 1024 * 1024
  const maxWidth = options.maxWidth || 1600
  const maxHeight = options.maxHeight || 1600
  const outputType = options.outputType || 'image/jpeg'
  const minQuality = options.minQuality || 0.55

  if (!isImageFile(file) || typeof FileReader === 'undefined' || typeof document === 'undefined') {
    return file
  }

  try {
    const image = await loadImage(file)
    let scale = Math.min(maxWidth / image.width, maxHeight / image.height, 1)
    let quality = options.quality || 0.82
    let bestBlob = null

    for (let i = 0; i < 7; i++) {
      const width = Math.max(1, Math.round(image.width * scale))
      const height = Math.max(1, Math.round(image.height * scale))
      const canvas = document.createElement('canvas')
      canvas.width = width
      canvas.height = height
      const context = canvas.getContext('2d')
      context.fillStyle = '#ffffff'
      context.fillRect(0, 0, width, height)
      context.drawImage(image, 0, 0, width, height)

      const blob = await canvasToBlob(canvas, outputType, quality)
      if (!blob) {
        return file
      }
      bestBlob = blob
      if (blob.size <= maxSize) {
        break
      }
      scale = scale * 0.82
      quality = Math.max(minQuality, quality - 0.08)
    }

    if (!bestBlob || bestBlob.size >= file.size) {
      return file
    }
    const fileName = file.name ? file.name.replace(/\.[^.]+$/, '.jpg') : 'upload.jpg'
    return new File([bestBlob], fileName, { type: outputType, lastModified: Date.now() })
  } catch (error) {
    return file
  }
}
