#Requires -Version 5.1
$ErrorActionPreference = 'Stop'

$ScriptDir = $PSScriptRoot
$ProjectRoot = (Resolve-Path (Join-Path $ScriptDir '..')).Path
$OutputDir = Join-Path $ProjectRoot 'output'
$StagingDir = Join-Path $ProjectRoot 'staging'
$VariantsDir = Join-Path $ProjectRoot 'variants'
$Version = (Get-Content (Join-Path $ProjectRoot 'VERSION') -Raw).Trim()

function Test-ZipExcludedPath {
    param(
        [Parameter(Mandatory)]
        [string] $FullPath
    )
    $name = [System.IO.Path]::GetFileName($FullPath)
    if ($name -eq '.DS_Store') { return $true }
    if ($FullPath -match '(?i)[\\/]__MACOSX[\\/]|(?i)^__MACOSX[\\/]') { return $true }
    if ($name -match '^\._') { return $true }
    return $false
}

function New-ZipFromDirectory {
    param(
        [Parameter(Mandatory)]
        [string] $SourceDirectory,
        [Parameter(Mandatory)]
        [string] $DestinationZip
    )
    Add-Type -AssemblyName System.IO.Compression
    Add-Type -AssemblyName System.IO.Compression.FileSystem

    $sourceResolved = (Resolve-Path -LiteralPath $SourceDirectory).Path.TrimEnd('\', '/')
    if (Test-Path -LiteralPath $DestinationZip) {
        Remove-Item -LiteralPath $DestinationZip -Force
    }
    $parent = Split-Path -Parent $DestinationZip
    if (-not (Test-Path -LiteralPath $parent)) {
        New-Item -ItemType Directory -Path $parent -Force | Out-Null
    }

    $zipStream = [System.IO.File]::Open(
        $DestinationZip,
        [System.IO.FileMode]::CreateNew,
        [System.IO.FileAccess]::ReadWrite,
        [System.IO.FileShare]::None
    )
    try {
        $zip = [System.IO.Compression.ZipArchive]::new($zipStream, [System.IO.Compression.ZipArchiveMode]::Create)
        try {
            Get-ChildItem -LiteralPath $sourceResolved -Recurse -Force -File -ErrorAction SilentlyContinue | ForEach-Object {
                $full = $_.FullName
                if (Test-ZipExcludedPath -FullPath $full) { return }
                $relative = $full.Substring($sourceResolved.Length).TrimStart('\', '/').Replace('\', '/')
                [void][System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $full, $relative)
            }
        } finally {
            $zip.Dispose()
        }
    } finally {
        $zipStream.Dispose()
    }
}

function Clear-OutputDirectory {
    Write-Host 'Loesche Output-Verzeichnis...'
    if (Test-Path -LiteralPath $OutputDir) {
        Remove-Item -LiteralPath $OutputDir -Recurse -Force
    }
    New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
    Write-Host 'Output-Verzeichnis geloescht.'
}

function Update-ManifestVersion {
    param(
        [Parameter(Mandatory)]
        [string] $BuildDir,
        [Parameter(Mandatory)]
        [string] $VariantFolderName
    )
    $manifestPath = Join-Path (Join-Path $BuildDir $VariantFolderName) 'config\omninx\manifest.ini'
    if (Test-Path -LiteralPath $manifestPath) {
        $lines = Get-Content -LiteralPath $manifestPath -Encoding UTF8
        $lines = $lines | ForEach-Object {
            if ($_ -match '^version=') { "version=$Version" } else { $_ }
        }
        $lines | Set-Content -LiteralPath $manifestPath -Encoding UTF8
    }
}

function Copy-VariantTree {
    param(
        [Parameter(Mandatory)]
        [string] $FromVariant,
        [Parameter(Mandatory)]
        [string] $ToFolder
    )
    $src = Join-Path $VariantsDir $FromVariant
    if (-not (Test-Path -LiteralPath $src)) {
        throw "Variant path not found: $src"
    }
    Get-ChildItem -LiteralPath $src -Force | Copy-Item -Destination $ToFolder -Recurse -Force
}

function New-BuildTempDir {
    $tmp = Join-Path ([System.IO.Path]::GetTempPath()) ("omninx-build-" + [Guid]::NewGuid().ToString('N'))
    New-Item -ItemType Directory -Path $tmp -Force | Out-Null
    return $tmp
}

function Build-Light {
    $buildDir = New-BuildTempDir
    try {
        Write-Host 'Baue OmniNX Light...'
        Get-ChildItem -LiteralPath $StagingDir -Force | Copy-Item -Destination $buildDir -Recurse -Force
        $variantPath = Join-Path $buildDir 'OmniNX Light'
        New-Item -ItemType Directory -Path $variantPath -Force | Out-Null
        Copy-VariantTree -FromVariant 'light' -ToFolder $variantPath
        Update-ManifestVersion -BuildDir $buildDir -VariantFolderName 'OmniNX Light'
        New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
        $zipPath = Join-Path $OutputDir "OmniNX-Light-$Version.zip"
        New-ZipFromDirectory -SourceDirectory $buildDir -DestinationZip $zipPath
    } finally {
        Remove-Item -LiteralPath $buildDir -Recurse -Force -ErrorAction SilentlyContinue
    }
}

function Build-Standard {
    $buildDir = New-BuildTempDir
    try {
        Write-Host 'Baue OmniNX Standard...'
        Get-ChildItem -LiteralPath $StagingDir -Force | Copy-Item -Destination $buildDir -Recurse -Force
        $variantPath = Join-Path $buildDir 'OmniNX Standard'
        New-Item -ItemType Directory -Path $variantPath -Force | Out-Null
        Copy-VariantTree -FromVariant 'light' -ToFolder $variantPath
        Copy-VariantTree -FromVariant 'standard' -ToFolder $variantPath
        Update-ManifestVersion -BuildDir $buildDir -VariantFolderName 'OmniNX Standard'
        New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
        $zipPath = Join-Path $OutputDir "OmniNX-Standard-$Version.zip"
        New-ZipFromDirectory -SourceDirectory $buildDir -DestinationZip $zipPath
    } finally {
        Remove-Item -LiteralPath $buildDir -Recurse -Force -ErrorAction SilentlyContinue
    }
}

function Build-Oc {
    $buildDir = New-BuildTempDir
    try {
        Write-Host 'Baue OmniNX OC...'
        Get-ChildItem -LiteralPath $StagingDir -Force | Copy-Item -Destination $buildDir -Recurse -Force
        $variantPath = Join-Path $buildDir 'OmniNX OC'
        New-Item -ItemType Directory -Path $variantPath -Force | Out-Null
        Copy-VariantTree -FromVariant 'light' -ToFolder $variantPath
        Copy-VariantTree -FromVariant 'standard' -ToFolder $variantPath
        Copy-VariantTree -FromVariant 'oc' -ToFolder $variantPath
        Update-ManifestVersion -BuildDir $buildDir -VariantFolderName 'OmniNX OC'
        New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
        $zipPath = Join-Path $OutputDir "OmniNX-OC-$Version.zip"
        New-ZipFromDirectory -SourceDirectory $buildDir -DestinationZip $zipPath
    } finally {
        Remove-Item -LiteralPath $buildDir -Recurse -Force -ErrorAction SilentlyContinue
    }
}

New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
Clear-OutputDirectory
Build-Light
Build-Standard
Build-Oc
Write-Host 'Alle Varianten gebaut.'
