[CmdletBinding()]
param(
	[ValidateSet("Product", "Channel", "AndroidCode", "AppleStoreBuild", "AppleDirectBuild", "WindowsPackage", "Json", "Verify")]
	[string] $Field = "Verify",

	[switch] $VerifyTag,

	[string] $VersionFile
)

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

if ([string]::IsNullOrWhiteSpace($VersionFile)) {
	$VersionFile = Join-Path $PSScriptRoot "..\..\version.properties"
}
$VersionFile = (Resolve-Path -LiteralPath $VersionFile).Path

function Read-VersionProperty {
	param([string] $Name)

	$prefix = "$Name="
	$matches = @(Get-Content -LiteralPath $VersionFile | Where-Object { $_.StartsWith($prefix) })
	if ($matches.Count -ne 1) {
		throw "Expected exactly one $Name entry in $VersionFile"
	}
	return $matches[0].Substring($prefix.Length)
}

function Convert-CanonicalInteger {
	param(
		[string] $Name,
		[string] $Value,
		[long] $Minimum,
		[long] $Maximum
	)

	if ($Value -notmatch "^(0|[1-9][0-9]*)$") {
		throw "$Name must be a canonical non-negative integer"
	}
	$number = 0L
	if (-not [long]::TryParse($Value, [ref] $number) -or $number -lt $Minimum -or $number -gt $Maximum) {
		throw "$Name must be between $Minimum and $Maximum"
	}
	return $number
}

$productVersion = Read-VersionProperty "PRODUCT_VERSION"
$releaseChannel = Read-VersionProperty "RELEASE_CHANNEL"
$windowsVersionEpochText = Read-VersionProperty "WINDOWS_VERSION_EPOCH"
$buildTimeUtc = $env:VNIDROP_BUILD_TIME_UTC
if ([string]::IsNullOrWhiteSpace($buildTimeUtc)) {
	$buildTimeUtc = [DateTime]::UtcNow.ToString(
		"yyyyMMddHHmmss",
		[Globalization.CultureInfo]::InvariantCulture
	)
}
if ($buildTimeUtc -notmatch "^[0-9]{14}$") {
	throw "VNIDROP_BUILD_TIME_UTC must use YYYYMMDDHHMMSS"
}
$parsedBuildTime = [DateTime]::MinValue
if (-not [DateTime]::TryParseExact(
		$buildTimeUtc,
		"yyyyMMddHHmmss",
		[Globalization.CultureInfo]::InvariantCulture,
		[Globalization.DateTimeStyles]::AssumeUniversal -bor [Globalization.DateTimeStyles]::AdjustToUniversal,
		[ref] $parsedBuildTime
	)) {
	throw "VNIDROP_BUILD_TIME_UTC is not a valid UTC timestamp"
}
$appleBuildNumber = $parsedBuildTime.ToString(
	"yyyyMMdd.HHmm.ss",
	[Globalization.CultureInfo]::InvariantCulture
)

if ($productVersion -notmatch "^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$") {
	throw "PRODUCT_VERSION must use canonical MAJOR.MINOR.PATCH integers"
}
$productParts = $productVersion.Split(".")
$productMajor = Convert-CanonicalInteger "PRODUCT_VERSION major" $productParts[0] 0 2099
$productMinor = Convert-CanonicalInteger "PRODUCT_VERSION minor" $productParts[1] 0 999
$productPatch = Convert-CanonicalInteger "PRODUCT_VERSION patch" $productParts[2] 0 999
if ($releaseChannel -notmatch "^[a-z][a-z0-9-]*$") {
	throw "RELEASE_CHANNEL contains unsupported characters"
}
$androidVersionCode = $productMajor * 1000000L + $productMinor * 1000L + $productPatch
if ($androidVersionCode -lt 1 -or $androidVersionCode -gt 2100000000L) {
	throw "Derived Android version code must be between 1 and 2100000000"
}
$windowsVersionEpoch = Convert-CanonicalInteger "WINDOWS_VERSION_EPOCH" $windowsVersionEpochText 1 65535
$windowsMajor = $productMajor + $windowsVersionEpoch
if ($windowsMajor -gt 65535) {
	throw "Derived Windows package major exceeds 65535"
}
$windowsPackageVersion = "$windowsMajor.$($productParts[1]).$($productParts[2]).0"

if ($VerifyTag -and $env:GITHUB_REF_TYPE -eq "tag" -and $env:GITHUB_REF_NAME -ne "v$productVersion") {
	throw "Release tag must be v$productVersion, got $($env:GITHUB_REF_NAME)"
}

$versionInfo = [ordered] @{
	productVersion = $productVersion
	releaseChannel = $releaseChannel
	androidVersionCode = $androidVersionCode
	appleStoreBuildNumber = $appleBuildNumber
	appleDirectBuildNumber = $appleBuildNumber
	windowsPackageVersion = $windowsPackageVersion
}

switch ($Field) {
	"Product" { $productVersion }
	"Channel" { $releaseChannel }
	"AndroidCode" { $androidVersionCode }
	"AppleStoreBuild" { $appleBuildNumber }
	"AppleDirectBuild" { $appleBuildNumber }
	"WindowsPackage" { $windowsPackageVersion }
	"Json" { $versionInfo | ConvertTo-Json -Compress }
	"Verify" {
		"VniDrop $productVersion ($releaseChannel), Android $androidVersionCode, Apple Store $appleBuildNumber, Apple Direct $appleBuildNumber, MSIX $windowsPackageVersion"
	}
}
