# --- [Command-Line Parameter Support] ---
param (
    [Parameter(Mandatory=$true, Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]$Country,                # e.g. ALL / US / Others

    [Parameter(Mandatory=$true, Position=1)]
    [ValidateRange(36,165)]
    [int]$Channel,                   # e.g. 36..165

    [Parameter(Mandatory=$true, Position=2)]
    [ValidateRange(0,8)]
    [string]$RateMbps,               # MCS"0".."8"
    
    [Parameter(Mandatory=$true, Position=3)]
    [ValidateNotNullOrEmpty()]
    [string]$TargetPower,            # Sepcification Power
                                     # e.g. 16, 17.5

    [Parameter(Mandatory=$true, Position=4)]
    [int]$BandwidthMHz,              # 11ac support 20MHz, 40MHz, 80MHz, 160MHz

    [Parameter()]
    [string]$COMPORT = "6"           # Default COM port for testing
)

# Always work at the script folder
Set-Location -Path $PSScriptRoot

# Validate COM port parameter
if (-not $COMPORT) {
    Write-Host "Missing COM port argument. Example: powershell.exe -File script.ps1 6" -ForegroundColor Red
    exit 1
}

Write-Host "Selected COM Port: $COMPORT" -ForegroundColor Yellow

### --- [Step 1] Initialize variables, log directory paths, and file names ---

# Customized serial numbers and Bus Prefix
# Expected FTDI serial number
$FTDI_TargetSerial = "FT8EBM6XA"
# Expected FTDI VID/PID
$FTDI_BusPrefix = "VID_0403+PID_6001"

# Locate wl_rc1.exe directory path
$wlExe = Join-Path -Path $PSScriptRoot -ChildPath "..\Files\wl_rc1.exe"
if (-not (Test-Path $wlExe)) {
    Write-Host "wl_rc1.exe not found: $wlExe" -ForegroundColor Red
    exit 2
}

$MFGTool_IF91X_WLAN_Tx_Path = (Get-Location).Path
# Write-Output "MFGTool Path: $MFGTool_IF91X_Download_Path"

# Obtain system time (format YYYYMMDDHHMMSS)
$timestamp = Get-Date -Format "yyyyMMddHHmmss"
# Write-Output "Timestamp: $timestamp"

# Read the content of UserScanInput.txt (two levels above the script)
# Write-Output "Folder File Content: $content"
$userInputPath = Join-Path -Path $PSScriptRoot -ChildPath "..\\..\\UserScanInput.txt"
if (-not (Test-Path $userInputPath)) {
    Write-Host "UserScanInput.txt not found: $userInputPath" -ForegroundColor Red
    exit 3
}
$content = Get-Content -Path $userInputPath -Raw

# Start recording the entire script output to a log file
# Get the path of the parent directory two levels up from the current working directory
$MiddlelogDir = Split-Path -Path $MFGTool_IF91X_WLAN_Tx_Path -Parent

# Combine the paths to get the final Logs directory path
$MiddlelogDir = Join-Path -Path $MiddlelogDir -ChildPath "Logs"
$logDir = Join-Path -Path $MiddlelogDir -ChildPath $content

# Replace the $(system time) part of the file name with $content
$Output_Txtfile = "${content}_wlan_11ac_tx_process-if91x_results_${timestamp}.txt"
$StandardOutput_Txtfile = "wlan_11ac_tx_process-if91x_results.txt"

# Check if the $content folder exists, and create it if not
$folderPath = Join-Path -Path $MiddlelogDir -ChildPath $content
if (-Not (Test-Path -Path $folderPath)) {
    Write-Host "Creating folder: $folderPath"
    New-Item -Path $folderPath -ItemType Directory | Out-Null
}

# Full path to the output file
$OutputFilePath = Join-Path -Path $logDir -ChildPath $Output_Txtfile

Write-Host "Resolved OutputFilePath: $OutputFilePath"
Write-Host "Resolved LogDir: $logDir"

# Check if the script has permissions to write to the file
if (-not (Test-Path -Path $OutputFilePath)) {
    try {
        New-Item -ItemType File -Path $OutputFilePath -Force | Out-Null
    } catch {
        Write-Host "Failed to create log file: $OutputFilePath" -ForegroundColor Red
        exit 4
    }
}

# Veda IF91x: Execute to do WLAN 5GHz transmit Tx performance testing
Write-Host "Log file: $OutputFilePath" -ForegroundColor Cyan
"==== IF91x 5GHz TX Test (11ac) ====" | Out-File -FilePath $OutputFilePath -Append

# Define a function to encapsulate Write a message to both console and log file
function Write-Log {
    param (
        [string]$Message
    )
    Write-Host $Message
    $Message | Out-File -FilePath $OutputFilePath -Append
}

Write-Log "Veda IF91x : Execute to transmit 5GHz Tx 11ac performance"

# Execute the external program and return the ExitCode, 
#   and write the standard output/error output to the log simultaneously
function Invoke-Proc {
    param(
        [string]$FilePath,
        [string[]]$ArgumentList
    )
    $psi = New-Object System.Diagnostics.ProcessStartInfo
    $psi.FileName = $FilePath
    $psi.Arguments = [string]::Join(' ', $ArgumentList)
    $psi.RedirectStandardOutput = $true
    $psi.RedirectStandardError  = $true
    $psi.UseShellExecute = $false
    $psi.CreateNoWindow = $true

    $p = New-Object System.Diagnostics.Process
    $p.StartInfo = $psi
    [void]$p.Start()
    $stdout = $p.StandardOutput.ReadToEnd()
    $stderr = $p.StandardError.ReadToEnd()
    $p.WaitForExit()

    if ($stdout) { $stdout | Out-File -FilePath $OutputFilePath -Append }
    if ($stderr) { ("[stderr] " + $stderr) | Out-File -FilePath $OutputFilePath -Append }

    return $p.ExitCode
}

Write-Log .

# Function to check error and stop execution with timeout
function Check-Error {
    param([int]$ExitCode, [string]$Step = "")
    if ($ExitCode -ne 0) {
        Write-Log "Error encountered at step: $Step (ExitCode=$ExitCode)"
        Write-Log "Transmit failure ..."
        Copy-Item -Path $OutputFilePath -Destination (Join-Path $logDir $StandardOutput_Txtfile) -Force
        exit $ExitCode
    }
}

Write-Log "Please be patient for about 5 seconds for Transmit Tx..."
Write-Log "...******************************..."
Write-Log "...*** DO NOT PRESS ANY KEY ! ***..."
Write-Log "...******************************..."
Write-Log ".."

### --- [Step 3] Scan and match FTDI device by serial and BusPrefix to obtain InstanceId ---

# --- Auto-correct COM port for WL (prefer COMX) ---
# Resolve FTDI COM port by VID/PID + Serial via Win32_SerialPort
function Resolve-WLComPort {
    param(
        [string]$VidPidPrefix,  # e.g., "VID_0403+PID_6001"
        [string]$TargetSerial   # e.g., "FT8EBIIHA"
    )
    try {
        # Convert "VID_0403+PID_6001" to a regex that can match both & and +, for example, "VID_0403.*PID_6001"
        $vidpidRegex = ($VidPidPrefix -replace '\+','.*')
        $rx = [regex]"$vidpidRegex.*$([regex]::Escape($TargetSerial))"

        # --- Plan A: Win32_SerialPort (Capture COMx directly) ---
        $ports = Get-CimInstance Win32_SerialPort -ErrorAction Stop | Where-Object {
            $_.PNPDeviceID -and $rx.IsMatch($_.PNPDeviceID)
        }
        if ($ports) {
            $best = $ports | Sort-Object {
                if ($_.DeviceID -match '^COM(\d+)$') { [int]$Matches[1] } else { 9999 }
            } | Select-Object -First 1
            if ($best -and $best.DeviceID -match '^COM(\d+)$') { return $Matches[1] }
        }

        # --- Plan B: Win32_PnPEntity 
        #             (Sometimes SerialPort cannot be captured, but there is Name: "USB Serial Port (COMX)") ---
        $pnps = Get-CimInstance Win32_PnPEntity -ErrorAction Stop | Where-Object {
            $_.PNPDeviceID -and $rx.IsMatch($_.PNPDeviceID) -and ($_.Name -match '\(COM\d+\)')
        }
        if ($pnps) {
            foreach ($n in $pnps) {
                if ($n.Name -match '\(COM(\d+)\)') { return $Matches[1] }
            }
        }

        # --- Plan C: Registry read FTDI PortName directly ---
        # HKLM:\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_0403+PID_6001+FT8FNBQUA\0000\Device Parameters\PortName
        $regPath = "HKLM:\SYSTEM\CurrentControlSet\Enum\FTDIBUS\{0}+{1}\0000\Device Parameters" -f $VidPidPrefix, $TargetSerial
        if (Test-Path $regPath) {
            $port = (Get-ItemProperty -Path $regPath -Name 'PortName' -ErrorAction Stop).PortName
            if ($port -match '^COM(\d+)$') { return $Matches[1] }
        }
    }
    catch {
        Write-Log ("Resolve-WLComPort error: {0}" -f $_.Exception.Message)
    }
    return $null
}

# Prefer VID/PID/SN detection; fallback: keep user COM if valid -> else Expected
$ExpectedWLCom = "3"

Write-Log ("Auto-detecting WL COM by VID/PID/SN (Prefix={0}, SN={1})..." -f $FTDI_BusPrefix, $FTDI_TargetSerial)
    $detected = Resolve-WLComPort -VidPidPrefix $FTDI_BusPrefix -TargetSerial $FTDI_TargetSerial
    if ($detected) {
        $COMPORT = $detected
    Write-Log ("Detected FTDI via VID/PID/SN -> COM{0}" -f $COMPORT)
    }
    else {
    # Check if the COM given by the user exists; if it exists, respect it and do not overwrite it
    $userOk = $false
    try {
        $userOk = (Get-CimInstance Win32_SerialPort | Where-Object { $_.DeviceID -eq ("COM{0}" -f $COMPORT) }) -ne $null
    } catch { $userOk = $false }

    if ($userOk) {
        Write-Log ("VID/PID detection failed; keeping user-specified COM{0}" -f $COMPORT)
    } else {
        Write-Log ("VID/PID detection failed; falling back to COM{0}" -f $ExpectedWLCom)
        $COMPORT = $ExpectedWLCom
    }
}
Write-Log ("WL will use COM{0}" -f $COMPORT)

### --- [Step 2] Scan and match FTDI device by serial and BusPrefix to obtain InstanceId ---

# Get Hardware VIDs/PIDs of connected FTDI bus via devcon (optional verification)
$devcon = "devcon64.exe"
if (-not (Get-Command $devcon -ErrorAction SilentlyContinue)) {
    Write-Log "WARNING: devcon64.exe not found in PATH. FTDI verification skipped."
} else {
    $devconOutput = & $devcon hwids *FTDI* 2>$null
    $instanceId = $devconOutput | Where-Object { $_ -like "*$FTDI_BusPrefix+$FTDI_TargetSerial\0000" } | Select-Object -First 1

    if (-not $instanceId) {
        Write-Log ("FTDI device not found by devcon (Serial={0}, Prefix={1})." -f $FTDI_TargetSerial, $FTDI_BusPrefix)
        # We do not hard-fail here since COM was already resolved; uncomment to enforce:
        # Copy-Item -Path $OutputFilePath -Destination (Join-Path $logDir $StandardOutput_Txtfile) -Force
        # exit 5
    } else {
        Write-Log "Found FTDI device Instance ID:"
        Write-Log ("    {0}" -f $instanceId)
    }
}

### --- [Step 3A] Resolve RF for 5GHz 11gn (from 4 args) ---
function Get-PhyByRate {
    param([string]$rate)
    $r = $rate.Trim()
    if (@("0","1","2","3","4","5","6","7","8") -contains $r)
        { return "11ac" }
    else
        { return $null }
}

$PHY = Get-PhyByRate $RateMbps
if (-not $PHY) {
    Write-Log ("[RF][ERR] Unsupported rate for 11ac: {0}" -f $RateMbps)
    exit 30
}

# Protocol rule
if ($PHY -eq "11ac" -and $Channel -eq 166) {
    Write-Log ("[RF][ERR] 11a is not allowed on CH166. Use CH36..165 or others.")
    exit 31
}

# 5GHz fixed band=a；legacy datarate use 5g_rate -v VHT-<MCS> -b 20
$BandArg  = @("a")
$RateArgs = @("5g_rate","-v",$RateMbps,"-s","1","-b","20")

Write-Log ("[RF] Country={0}  PHY={1}  CH={2}  BW={3}MHz  Rate=VHT-MCS{4}" -f `
            $Country,$PHY,$Channel,$BandwidthMHz,$RateMbps)

### --- [Step 3] Run WL tool, with logging and error check ---
# Wrapper for wl_rc1.exe commands with logging and error check
function Invoke-WL {
    param(
        [string[]]$Arguments,   # Avoid using the name "Args" to prevent clash with $args
        [string]$Label
    )
    if (-not $Arguments -or $Arguments.Count -eq 0) {
        Write-Log "Invoke-WL called with empty argument list. Label='$Label'"
        Check-Error -ExitCode -1 -Step "Invoke-WL(empty)"
        return
    }
    $wlproc = "./wl_rc1.exe " + ($Arguments -join ' ')
    Write-Log ">> $wlproc"
    $code = Invoke-Proc -FilePath $wlExe -ArgumentList $Arguments
    Check-Error -ExitCode $code -Step $Label
}

Write-Log "..."
Write-Log (".. Wi-Fi Transmit Tx {0} (5GHz) .." -f $PHY)
# Sequence of commands for WLAN 5GHz 11a TX test
Invoke-WL -Arguments @("--serial",$COMPORT,"ver")                                 -Label "ver"
Invoke-WL -Arguments @("--serial",$COMPORT,"cur_etheraddr")                       -Label "cur_etheraddr"
Invoke-WL -Arguments @("--serial",$COMPORT,"pkteng_stop","tx")                    -Label "pkteng_stop tx"
Invoke-WL -Arguments @("--serial",$COMPORT,"down")                                -Label "down"
Invoke-WL -Arguments @("--serial",$COMPORT,"spect","0")                           -Label "spect 0"
Invoke-WL -Arguments @("--serial",$COMPORT,"mpc","0")                             -Label "mpc 0"
Invoke-WL -Arguments @("--serial",$COMPORT,"phy_watchdog","0")                    -Label "phy_watchdog 0"
#Invoke-WL -Arguments @("--serial",$COMPORT,"country","ALL")                       -Label "country ALL"
#Invoke-WL -Arguments @("--serial",$COMPORT,"band","b")                            -Label "band b"
#Invoke-WL -Arguments @("--serial",$COMPORT,"channel","1")                         -Label "channel 1"
Invoke-WL -Arguments @("--serial",$COMPORT,"country",$Country)                    -Label ("country {0}" -f $Country)
Invoke-WL -Arguments @("--serial",$COMPORT,"band",$BandArg)                       -Label ("band {0}" -f $BandArg)
#Invoke-WL -Arguments @("--serial",$COMPORT,"channel",$Channel)                    -Label ("channel {0}" -f $Channel)
Invoke-WL -Arguments @("--serial", $COMPORT, "chanspec", ("{0}/{1}" -f $Channel, $BandwidthMHz)) -Label ("chanspec {0}/{1}" -f $Channel, $Bandwidth)
Invoke-WL -Arguments @("--serial",$COMPORT,"mimo_txbw","-1")                      -Label "mimo_txbw -1"
Invoke-WL -Arguments @("--serial",$COMPORT,"up")                                  -Label "up"
Invoke-WL -Arguments @("--serial",$COMPORT,"phy_forcecal","1")                    -Label "phy_forcecal 1"
Invoke-WL -Arguments @("--serial",$COMPORT,"scansuppress","1")                    -Label "scansuppress 1"
Invoke-WL -Arguments @("--serial",$COMPORT,"ldpc_cap","1")                        -Label "ldpc_cap 1"
Invoke-WL -Arguments @("--serial",$COMPORT,"phy_set_ant","0x10")                  -Label "phy_set_ant 0x10"
Invoke-WL -Arguments @("--serial",$COMPORT,"txcore","-s","1","-c","1")            -Label "txcore -s 1 -c 1"
$ArgsRate = @("--serial",$COMPORT) + $RateArgs
Invoke-WL -Arguments $ArgsRate                                                    -Label ("{0}" -f ($RateArgs -join ' '))
#Invoke-WL -Arguments @("--serial",$COMPORT,"phy_txpwrctrl","1")                   -Label "phy_txpwrctrl 1"
#Invoke-WL -Arguments @("--serial",$COMPORT,"txpwr1","-1")                         -Label "txpwr1 -1"
Invoke-WL -Arguments @("--serial",$COMPORT,"txpwr1","-o","-q",$TargetPower)  -Label ("wl txpwr1 -o -q {0}" -f $TargetPower)

Invoke-WL -Arguments @("--serial",$COMPORT,"pkteng_start","00:11:22:33:44:55","tx","1000","1024","0") -Label "pkteng_start"

# Final success message and log copy
Write-Log "....."
Write-Log "WLAN 5GHz Transmit Tx successfully ..."

# Copy Process Log with MAC as Standard naming format file
Copy-Item -Path $OutputFilePath -Destination (Join-Path $logDir $StandardOutput_Txtfile) -Force

Write-Log "Done."
