foreach ($arg in $args) 
{
  if ($arg -eq "clang")   { $Global:clang   = $true }
  if ($arg -eq "msvc")    { $Global:msvc    = $true }
  if ($arg -eq "vulkan")  { $Global:vulkan  = $true }
  if ($arg -eq "pack")    { $Global:pack    = $true }
  if ($arg -eq "packer")  { $Global:packer  = $true }
  if ($arg -eq "debug")   { $Global:debug   = $true }
  if ($arg -eq "release") { $Global:release = $true }
}

if ($Global:vulkan -ne $true)                               { $Global:vulkan = $true }
if ($Global:clang -ne $true -and $Global:msvc -ne $true)    { $Global:clang = $true }
if ($Global:debug -ne $true -and $Global:release -ne $true) { $Global:debug = $true }

if ($Global:vulkan) { $Global:render_flag = "-DSTG_VULKAN_RENDERER" }

$out_name = "Gears.exe"
$source_files = "..\src\entry_windows.c .\vma.o"

$vulkan_include="C:\VulkanSDK\1.4.304.1\Include"

$clang_out = "-o"
$clang_compiler = "clang"
$clang_includes = "-I..\src\ -I..\external\ -I$($vulkan_include)"
$clang_link = "-luser32 -lkernel32 -lGdi32"
$clang_common = "$($clang_includes) $($Global:render_flag) $($clang_link) -fuse-ld=lld-link --target=x86_64-pc-windows-msvc -DCOMPILER_CLANG -std=c23 -Xclang -flto-visibility-public-std -Wno-unknown-warning-option -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wmicrosoft-enum-forward-reference -Wno-nullability-completeness -Wno-for-loop-analysis -DVMA_STATIC_VULKAN_FUNCTIONS=0 -ferror-limit=60"
$clang_debug = "$($clang_compiler) -g -O2 -DBUILD_DEBUG $($source_files) $($clang_common) $($clang_out) $($out_name)"
$clang_release = "$($clang_compiler) -O2 $($source_files) $($clang_common) $($clang_out) $($out_name)"
$clang_test = "$($clang_compiler) -O2 -DBUILD_TEST $($clang_common) $($clang_out) $($out_name)"

$vma_out_name = "vma.o"
$clang_vma_compiler = "clang++"
$clang_vma_includes = "-I..\external\vma\"
$clang_vma_common = "$($clang_vma_includes) -Wl --target=x86_64-pc-windows-msvc -fuse-ld=lld-link -Wno-everything -D_USE_MATH_DEFINES -c -std=c++20 -I$($vulkan_include)"
$clang_vma_debug = "$($clang_vma_compiler) ..\external\vma\vma.cpp -g -O0 $($clang_vma_common) $($clang_out) $($vma_out_name)"
$clang_vma_release = "$($clang_vma_compiler) ..\external\vma\vma.cpp -O2 $($clang_vma_common) $($clang_out) $($vma_out_name)"

$packer_src = "..\src\packer.c .\vma.o"
$packer_out_name = "Packer.exe"
$clang_packer_include = "-I..\src\ -I..\external\"
$clang_packer_debug = "$($clang_compiler) $($packer_src) -g -O0 -DBUILD_DEBUG=1 $($clang_common) $($clang_out) $($packer_out_name)"
$clang_packer_release = "$($clang_compiler) $($packer_src) -O2 -DBUILD_DEBUG=1 $($clang_common) $($clang_out) $($packer_out_name)"

if ($Global:clang)
{
  $Global:compile_debug           = $clang_debug
  $Global:compile_release         = $clang_release
  $Global:compile_vma_debug       = $clang_vma_debug
  $Global:compile_vma_release     = $clang_vma_release
  $Global:compile_packer_debug    = $clang_packer_debug
  $Global:compile_packer_release  = $clang_packer_release
}

if ($Global:release)
{
  $Global:compile         = $Global:compile_release
  $Global:compile_vma     = $Global:compile_vma_release
  $Global:compile_packer  = $Global:compile_packer_release
}

if ($Global:debug)
{
  $Global:compile         = $Global:compile_debug
  $Global:compile_vma     = $Global:compile_vma_debug
  $Global:compile_packer  = $Global:compile_packer_debug
}

if (-not (Test-Path -Path ".\build" -PathType "Container"))
{
  New-Item -Path . -Name "build" -ItemType "Directory"
}

Push-Location build

if (-not (Test-Path -Path ".\assets.sgp" -PathType "Leaf"))
{
  New-Item -Path . -Name "assets.sgp" -ItemType "File"
}

if (-not (Test-Path -Path ".\Packer.exe" -PathType "Leaf") -or $Global:packer)
{
  Invoke-Expression "$($Global:compile_packer)"
}

if ($Global:vulkan)
{
  if (-not (Test-Path -Path ".\shaders" -PathType "Container"))
  {
    New-Item -Path . -Name "shaders" -ItemType "Container"
  }

  if (-not (Test-Path -Path ".\shaders\glsl" -PathType "Container"))
  {
    New-Item -Path ".\shaders" -Name "glsl" -ItemType "Container"
  }

  $glslc = "glslc"
  $glslc_flags = "--target-spv=spv1.6 -std=460"
  $glslc_out = "-o.\shaders\glsl\"

  $shader_files = Get-ChildItem "..\src\shaders\glsl\*.*.glsl"
  foreach ($file in $shader_files)
  {
    $stage = ""
    switch -Wildcard ($file.Name)
    {
      "*.vert.glsl" { $stage = "-fshader-stage=vert"; break }
      "*.frag.glsl" { $stage = "-fshader-stage=frag"; break }
      "*.tesc.glsl" { $stage = "-fshader-stage=tesc"; break }
      "*.tese.glsl" { $stage = "-fshader-stage=tese"; break }
      "*.geom.glsl" { $stage = "-fshader-stage=geom"; break }
      "*.comp.glsl" { $stage = "-fshader-stage=comp"; break }
      default       { continue }
    }

    Invoke-Expression "$($glslc) $($glslc_flags) $($stage) $($file.FullName) $($glslc_out)$($file.BaseName).spv"
  }
}

if ($Global:pack)
{
  Pop-Location
  Invoke-Expression ".\build\$($packer_out_name)"
  Push-Location build
}

if (-not (Test-Path -Path ".\$($vma_out_name)" -PathType "Leaf"))
{
  Invoke-Expression "$($Global:compile_vma)"
}

Invoke-Expression "$($Global:compile)"

Pop-Location
