import { ImageData } from "."
import { Image } from "../api"
import { downloadImage } from "./download"
import { compressImage, getImageSize, rasterizeSvg } from "./render"
import { uploadImage } from "./upload"

const MESSAGE_LIMIT = Math.round(1048576 * 0.95)
const MIN_SIDE_LENGTH = 128

export const downloadImagesAndMakePreviews = async (imageStorageDirectory: string | undefined, images: Image[]) => {
  const imagePromises = images.map(async (imageData) => {
    if (!imageData?.url) {
      return null
    }

    const imageUrl = imageData.url
    const id = imageData.imageId
    const image = await downloadImage(imageUrl)

    let pathOrUrl: string
    if (imageStorageDirectory) {
      const path = await uploadImage(imageStorageDirectory, id, image)
      pathOrUrl = `file://${path}`
    } else {
      pathOrUrl = imageUrl
    }

    let previewData: ImageData
    if (image.mimeType === 'image/svg+xml') {
      previewData = await rasterizeSvg(image.data)
    } else {
      previewData = await compressImage(image)
    }

    const imageSize = await getImageSize(previewData)

    return {...image, url: imageUrl, id, pathOrUrl, previewData, ...imageSize}
  })

  const downloadedImages = (await Promise.all(imagePromises)).filter((image) => image !== null)

  const minSideSize = Math.min(...downloadedImages.map(image => Math.min(image.width, image.height)))
  
  const calculateTotalLength = (images: {previewData: ImageData}[]) => images.map(image => image.previewData.data.length).reduce((a, b) => a + b, 0)

  let scale = 1.0
  while (calculateTotalLength(downloadedImages) > MESSAGE_LIMIT && scale * 0.5 * minSideSize >= MIN_SIDE_LENGTH - 1e-6) {
    scale *= 0.5
    const scalePromises = downloadedImages.map(async (image) => {
      if (image.mimeType === 'image/svg+xml') {
        image.previewData = await rasterizeSvg(image.data, scale)
      } else {
        image.previewData = await compressImage(image, scale)
      }
    })
    await Promise.all(scalePromises)
  }

  let totalLength = 0
  let previews = []
  for (const {previewData} of downloadedImages) {
    if (totalLength + previewData.data.length > MESSAGE_LIMIT) {
      break
    }
    totalLength += previewData.data.length
    previews.push({
      type: 'image',
      ...previewData,
    })
  }

  return {
    downloadedImages, 
    previews,
  }
}
