#!/usr/bin/env pwsh
#Requires -Version 7.0

[CmdletBinding()]
param(
  [switch] $Test,
  [ValidateRange(1,25)]
  [int] $Day,

  [switch] $Release,
  [switch] $NoStrip,

  [string[]] $ExtraOdinFlags = @()
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$C = @{
  White = "`e[1;37m"
  Green = "`e[1;32m"
  Red   = "`e[1;31m"
  End   = "`e[0m"
}

function Fail([string]$msg) {
  Write-Host ("{0}{1}{2}" -f $C.Red, $msg, $C.End)
  exit 1
}

function Run([string]$exe, [string[]]$arguments) {
  & $exe @arguments
  if ($LASTEXITCODE -ne 0) { Fail "FAIL ($LASTEXITCODE): $exe $($arguments -join ' ')" }
}

$projectName = Split-Path -Leaf (Get-Location).Path
$binName     = [System.IO.Path]::ChangeExtension($projectName, '.exe')

$binDir  = Join-Path (Get-Location) 'bin'
if (-not (Test-Path $binDir -PathType Container)) { New-Item -ItemType Directory -Path $binDir | Out-Null }

$commonFlags = if ($Release) {
  @('-o:speed','-no-bounds-check','-disable-assert','-extra-linker-flags:"-Wl,--gc-sections"')
} else {
  @('-debug','-vet','-strict-style','-warnings-as-errors')
}

Write-Host ("{0}Using Odin flags:{1}" -f $C.White, $C.End)
($commonFlags + $ExtraOdinFlags) | ForEach-Object { Write-Host "  $_" }

Push-Location $binDir
try {
  if ($Test) {
    Write-Host ""
    Write-Host ("{0}Running tests{1}" -f $C.White, $C.End)

    if ($PSBoundParameters.ContainsKey('Day')) {
      $dayStr = "{0:D2}" -f $Day
      Run 'odin' (@('test', "../src/day_$dayStr") + $commonFlags + $ExtraOdinFlags)
    } else {
      Run 'odin' (@('test','../src','--all-packages') + $commonFlags + $ExtraOdinFlags)
    }
    Write-Host ""
    return
  }

  $outPath = Join-Path (Get-Location) $binName
  Write-Host ("{0}Building:{1} {2}" -f $C.White, $C.End, $outPath)

  Run 'odin' (@('build','../src',"-out:$binName",'-show-timings') + $commonFlags + $ExtraOdinFlags)

  Write-Host ""
  Write-Host ("{0}OK{1}" -f $C.Green, $C.End)

  if ($Release -and -not $NoStrip) {
    Run 'strip' @('-s', (Join-Path (Get-Location) $binName))
  }
}
finally {
  Pop-Location
}