Param(
  [switch]$Release
)

$Compiler = "cl.exe"
$Linker = "lib.exe"

$GeneralFlags = "/Wall /WX /wd4996 /wd4464 /wd5105 /EHs"
$CStd = "/std:c11"
$CppStd = "/std:c++14"
$LibraryFlags = "/c"

$Kernel = (Get-ChildItem Env:OS).Value
$Machine = (Get-ChildItem Env:PROCESSOR_ARCHITECTURE).Value
$Platform = "${Kernel}_${Machine}"

$IncludeDirs = "/I src"
$SrcFiles = "src/wapp.c"

$TestIncludeDirs = Get-ChildItem -Path tests -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
$TestCSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
$TestCppSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.cc -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}

If ($Release -eq $True) {
  $GeneralFlags += " /O2 /Og"
  $BuildType = "Release"
} Else {
  $GeneralFlags += " /Zi /Od /fsanitize=address"
  $BuildType = "Debug"
}

$BuildDir = "./libwapp-build/${Platform}-${BuildType}"
$ObjDir = "$BuildDir/objects"
$OutDir = "$BuildDir/output"
$TestsDir = "$BuildDir/tests"

$LibOutput = "$OutDir/libwapp.lib"
$Objects = "/Fo:$ObjDir/"
$LibOutputFlags = "/OUT:$LibOutput"

$TestCOutputBasename = "wapptest"
$TestCOutputFlags = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestCOutputBasename"

$TestCppOutputBasename = "wapptestcc"
$TestCppOutputFlags = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestCppOutputBasename"

If (Test-Path $BuildDir) {
  Remove-Item $BuildDir -Recurse -Force
}

mkdir -p $ObjDir > $null
mkdir -p $OutDir > $null
mkdir -p $TestsDir > $null

# Run code generation
Invoke-Expression "python -m codegen"

# Build and run C tests
Invoke-Expression "$Compiler $GeneralFlags $CStd $IncludeDirs $TestIncludeDirs $SrcFiles $TestCSrcFiles $TestCOutputFlags" -ErrorAction Stop
Invoke-Expression "$TestsDir/$TestCOutputBasename.exe"

$Status = $LASTEXITCODE
If ($Status -ne 0) {
  Remove-Item $TestsDir -Recurse -Force
  Write-Error "Tests failed"
  Exit 1
}

# Build library
Invoke-Expression "$Compiler $GeneralFlags $CStd $LibraryFlags $SrcFiles $Objects"
Invoke-Expression "$Linker $ObjDir/*.obj $LibOutputFlags"

# Build and run C++ tests
Invoke-Expression "$Compiler $GeneralFlags $CppStd $IncludeDirs $TestIncludeDirs $LibOutput $TestCppSrcFiles $TestCppOutputFlags" -ErrorAction Stop
Invoke-Expression "$TestsDir/$TestCppOutputBasename.exe"

Remove-Item $TestsDir -Recurse -Force
