param(
    [Parameter(Mandatory = $true)]
    [string]$InputPath,

    [ValidateSet("logo", "masthead", "feature", "card", "gallery", "banner", "platform-icon", "profile")]
    [string]$Preset = "gallery",

    [string]$OutputDir = "public/img/generated",

    [string]$OutputName = ""
)

$ErrorActionPreference = "Stop"

$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
$resolvedInput = Resolve-Path $InputPath

if ([System.IO.Path]::IsPathRooted($OutputDir)) {
    $resolvedOutputDir = $OutputDir
}
else {
    $resolvedOutputDir = Join-Path $repoRoot $OutputDir
}

New-Item -ItemType Directory -Path $resolvedOutputDir -Force | Out-Null

$presets = @{
    logo = @{
        Width = 1200
        Height = 0
        Mode = "fit"
        Suffix = "logo"
    }
    masthead = @{
        Width = 860
        Height = 0
        Mode = "fit"
        Suffix = "masthead"
    }
    feature = @{
        Width = 900
        Height = 506
        Mode = "crop"
        Suffix = "feature"
    }
    card = @{
        Width = 600
        Height = 338
        Mode = "crop"
        Suffix = "card"
    }
    gallery = @{
        Width = 480
        Height = 270
        Mode = "crop"
        Suffix = "gallery"
    }
    banner = @{
        Width = 1920
        Height = 1080
        Mode = "crop"
        Suffix = "banner"
    }
    "platform-icon" = @{
        Width = 256
        Height = 256
        Mode = "pad"
        Suffix = "platform-icon"
    }
    profile = @{
        Width = 512
        Height = 512
        Mode = "crop"
        Suffix = "profile"
    }
}

function Get-ImageFiles {
    param([string]$Path)

    $item = Get-Item -LiteralPath $Path

    if ($item.PSIsContainer) {
        return Get-ChildItem -LiteralPath $Path -File |
            Where-Object { $_.Extension -match "^\.(png|jpg|jpeg|bmp)$" }
    }

    return @($item)
}

function Resize-Image {
    param(
        [string]$SourcePath,
        [string]$DestinationPath,
        [int]$TargetWidth,
        [int]$TargetHeight,
        [string]$Mode
    )

    Add-Type -AssemblyName System.Drawing

    $image = [System.Drawing.Image]::FromFile($SourcePath)

    if ($TargetHeight -eq 0) {
        $TargetHeight = [int][Math]::Round($image.Height * $TargetWidth / $image.Width)
    }

    $bitmap = New-Object System.Drawing.Bitmap $TargetWidth, $TargetHeight
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap)

    $graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
    $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
    $graphics.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
    $graphics.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
    $graphics.Clear([System.Drawing.Color]::Transparent)

    if ($Mode -eq "crop") {
        $scale = [Math]::Max($TargetWidth / $image.Width, $TargetHeight / $image.Height)
        $sourceWidth = [int][Math]::Round($TargetWidth / $scale)
        $sourceHeight = [int][Math]::Round($TargetHeight / $scale)
        $sourceX = [int][Math]::Max(0, [Math]::Round(($image.Width - $sourceWidth) / 2))
        $sourceY = [int][Math]::Max(0, [Math]::Round(($image.Height - $sourceHeight) / 2))

        $sourceRect = New-Object System.Drawing.Rectangle $sourceX, $sourceY, $sourceWidth, $sourceHeight
        $destRect = New-Object System.Drawing.Rectangle 0, 0, $TargetWidth, $TargetHeight
        $graphics.DrawImage($image, $destRect, $sourceRect, [System.Drawing.GraphicsUnit]::Pixel)
    }
    elseif ($Mode -eq "pad") {
        $scale = [Math]::Min($TargetWidth / $image.Width, $TargetHeight / $image.Height)
        $drawWidth = [int][Math]::Round($image.Width * $scale)
        $drawHeight = [int][Math]::Round($image.Height * $scale)
        $drawX = [int][Math]::Round(($TargetWidth - $drawWidth) / 2)
        $drawY = [int][Math]::Round(($TargetHeight - $drawHeight) / 2)

        $destRect = New-Object System.Drawing.Rectangle $drawX, $drawY, $drawWidth, $drawHeight
        $graphics.DrawImage($image, $destRect)
    }
    else {
        $graphics.DrawImage($image, 0, 0, $TargetWidth, $TargetHeight)
    }

    $bitmap.Save($DestinationPath, [System.Drawing.Imaging.ImageFormat]::Png)

    $graphics.Dispose()
    $bitmap.Dispose()
    $image.Dispose()
}

$presetConfig = $presets[$Preset]
$files = Get-ImageFiles -Path $resolvedInput

foreach ($file in $files) {
    $name = if ($OutputName -and $files.Count -eq 1) {
        $OutputName
    }
    else {
        "{0}-{1}.png" -f $file.BaseName, $presetConfig.Suffix
    }

    if ([System.IO.Path]::GetExtension($name) -eq "") {
        $name = "$name.png"
    }

    $destination = Join-Path $resolvedOutputDir $name

    Resize-Image `
        -SourcePath $file.FullName `
        -DestinationPath $destination `
        -TargetWidth $presetConfig.Width `
        -TargetHeight $presetConfig.Height `
        -Mode $presetConfig.Mode

    Write-Output ("{0} -> {1}" -f $file.Name, $destination)
}
