param(
  [string]$OutputPath = ""
)

$ErrorActionPreference = "Stop"
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
  $OutputPath = Join-Path $repoRoot "companion\src\Lumi.Companion.App\Assets\Lumi.Companion.ico"
}
$OutputPath = [System.IO.Path]::GetFullPath($OutputPath)
$sizes = @(16, 32, 48, 256)

function New-LumiIconFrame {
  param([int]$Size)

  $radius = [Math]::Max(3, [Math]::Round($Size * 0.22))
  $center = ($Size - 1) / 2.0
  $diamondRadius = $Size * 0.36
  $maskStride = [Math]::Ceiling($Size / 32.0) * 4
  $pixels = New-Object byte[] ($Size * $Size * 4)

  for ($y = 0; $y -lt $Size; $y++) {
    for ($x = 0; $x -lt $Size; $x++) {
      $inside = $true
      if (!(($x -ge $radius -and $x -lt $Size - $radius) -or ($y -ge $radius -and $y -lt $Size - $radius))) {
        $cornerX = if ($x -lt $radius) { $radius } else { $Size - $radius - 1 }
        $cornerY = if ($y -lt $radius) { $radius } else { $Size - $radius - 1 }
        $dx = $x - $cornerX
        $dy = $y - $cornerY
        $inside = (($dx * $dx) + ($dy * $dy)) -le ($radius * $radius)
      }
      $diamond = (([Math]::Abs($x - $center) / $diamondRadius) + ([Math]::Abs($y - $center) / $diamondRadius)) -le 1
      $target = ((($Size - 1 - $y) * $Size) + $x) * 4
      $pixels[$target] = if ($diamond -and $inside) { 255 } else { 200 }
      $pixels[$target + 1] = if ($diamond -and $inside) { 255 } else { 183 }
      $pixels[$target + 2] = if ($diamond -and $inside) { 255 } else { 40 }
      $pixels[$target + 3] = if ($inside) { 255 } else { 0 }
    }
  }

  $stream = [System.IO.MemoryStream]::new()
  $writer = [System.IO.BinaryWriter]::new($stream)
  $writer.Write([int]40)
  $writer.Write([int]$Size)
  $writer.Write([int]($Size * 2))
  $writer.Write([uint16]1)
  $writer.Write([uint16]32)
  $writer.Write([int]0)
  $writer.Write([int]$pixels.Length)
  $writer.Write([int]0)
  $writer.Write([int]0)
  $writer.Write([int]0)
  $writer.Write([int]0)
  $writer.Write($pixels)
  $writer.Write((New-Object byte[] ($maskStride * $Size)))
  $writer.Flush()
  $result = $stream.ToArray()
  $writer.Dispose()
  $stream.Dispose()
  return ,$result
}

[byte[][]]$frames = @($sizes | ForEach-Object { ,(New-LumiIconFrame -Size $_) })
$directorySize = 6 + ($frames.Count * 16)
$offset = $directorySize
$output = [System.IO.MemoryStream]::new()
$binary = [System.IO.BinaryWriter]::new($output)
$binary.Write([uint16]0)
$binary.Write([uint16]1)
$binary.Write([uint16]$frames.Count)

for ($index = 0; $index -lt $frames.Count; $index++) {
  $size = $sizes[$index]
  $frame = $frames[$index]
  $encodedSize = if ($size -eq 256) { 0 } else { $size }
  $binary.Write([byte]$encodedSize)
  $binary.Write([byte]$encodedSize)
  $binary.Write([byte]0)
  $binary.Write([byte]0)
  $binary.Write([uint16]1)
  $binary.Write([uint16]32)
  $binary.Write([int]$frame.Length)
  $binary.Write([int]$offset)
  $offset += $frame.Length
}
foreach ($frame in $frames) { $binary.Write($frame) }
$binary.Flush()

$directory = Split-Path -Parent $OutputPath
[System.IO.Directory]::CreateDirectory($directory) | Out-Null
[System.IO.File]::WriteAllBytes($OutputPath, $output.ToArray())
$binary.Dispose()
$output.Dispose()
Write-Host "Generated Lumi Companion icon: $OutputPath"
