import { existsSync, mkdirSync, rmSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { Jimp } from 'jimp'
import pngToIco from 'png-to-ico'

const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
const INSTALLER_SOURCE = path.join(
  rootDir,
  'assets/logos/farmcontrolinstaller.png'
)
const UNINSTALLER_SOURCE = path.join(
  rootDir,
  'assets/logos/farmcontroluninstaller.png'
)

const MAC_ICONSET_ENTRIES = [
  { name: 'icon_16x16.png', size: 16 },
  { name: 'icon_16x16@2x.png', size: 32 },
  { name: 'icon_32x32.png', size: 32 },
  { name: 'icon_32x32@2x.png', size: 64 },
  { name: 'icon_128x128.png', size: 128 },
  { name: 'icon_128x128@2x.png', size: 256 },
  { name: 'icon_256x256.png', size: 256 },
  { name: 'icon_256x256@2x.png', size: 512 },
  { name: 'icon_512x512.png', size: 512 },
  { name: 'icon_512x512@2x.png', size: 1024 }
]

const WIN_ICO_SIZES = [16, 32, 48, 256]

async function resizePng(sourceImage, size) {
  return sourceImage
    .clone()
    .resize({ w: size, h: size })
    .getBuffer('image/png')
}

async function writePng(filePath, sourceImage, size) {
  const png = await resizePng(sourceImage, size)
  await Bun.write(filePath, png)
  return png
}

async function writeWindowsIco(sourceImage, icoPath) {
  const icoPngs = []
  for (const size of WIN_ICO_SIZES) {
    icoPngs.push(await resizePng(sourceImage, size))
  }

  await Bun.write(icoPath, await pngToIco(icoPngs))
  console.log(`prepare-installer-icons: wrote ${icoPath}`)
}

async function main() {
  if (!existsSync(INSTALLER_SOURCE)) {
    console.error(
      `prepare-installer-icons: source image not found: ${INSTALLER_SOURCE}`
    )
    process.exit(1)
  }

  if (!existsSync(UNINSTALLER_SOURCE)) {
    console.error(
      `prepare-installer-icons: source image not found: ${UNINSTALLER_SOURCE}`
    )
    process.exit(1)
  }

  const installerImage = await Jimp.read(INSTALLER_SOURCE)
  if (installerImage.width < 256 || installerImage.height < 256) {
    console.warn(
      `prepare-installer-icons: installer source is ${installerImage.width}x${installerImage.height}; recommend at least 256x256`
    )
  }

  const uninstallerImage = await Jimp.read(UNINSTALLER_SOURCE)
  if (uninstallerImage.width < 256 || uninstallerImage.height < 256) {
    console.warn(
      `prepare-installer-icons: uninstaller source is ${uninstallerImage.width}x${uninstallerImage.height}; recommend at least 256x256`
    )
  }

  const assetsDir = path.join(rootDir, 'assets')
  mkdirSync(assetsDir, { recursive: true })

  const iconsetDir = path.join(assetsDir, 'installer.iconset')
  rmSync(iconsetDir, { recursive: true, force: true })
  mkdirSync(iconsetDir, { recursive: true })

  for (const entry of MAC_ICONSET_ENTRIES) {
    await writePng(
      path.join(iconsetDir, entry.name),
      installerImage,
      entry.size
    )
  }

  console.log(`prepare-installer-icons: wrote ${iconsetDir}`)
  await writeWindowsIco(installerImage, path.join(assetsDir, 'installer.ico'))
  await writeWindowsIco(
    uninstallerImage,
    path.join(assetsDir, 'uninstaller.ico')
  )
}

main().catch((error) => {
  console.error(`prepare-installer-icons: ${error.message}`)
  process.exit(1)
})
