if ($args.count -ne 2) {
    Write-Host "Need argument 1:  Host IP or Hostname"
    Write-Host "Need argument 2:  Host Port"
    exit 1
}

$socket = New-Object System.Net.Sockets.TcpClient
$socket.connect($args[0], [int]$args[1])
$stream = $socket.GetStream()
$buf = New-Object byte[] 4096
$messages_lost = 0

# TODO: figure out how this works
[console]::TreatControlCAsInput = $true

while ($socket.Connected) {
    while ($stream.DataAvailable) {
        $n_read = $stream.Read($buf, 0, $buf.Length)
        $text = [System.Text.Encoding]::UTF8.GetString($buf, 0, $n_read)
        Write-Host $text -NoNewLine

        if ($text -match '\x48\x1B\x44') {
            $messages_lost += 1
        }
    }
    if ($messages_lost -gt 0) {
        # >2018
        # >still can't get vt100 right
        # microsoft in charge of conserving bandwidth
        $stream.Write([Byte[]] (0x12), 0, 1)
        $messages_lost = 0
    }
    while ([console]::KeyAvailable) {
    	$key = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
        $kc = $key.VirtualKeyCode
        if ($kc -eq 3) {
            # TODO: doesn't work since TreatControlCAsInput does nothing
            Write-Host "`n`n*** shutting down`n`n"
            $socket.Close()
            $socket.Dispose()
            Start-Sleep -Milliseconds 200
            exit 0
        }
        $text = $key.Character
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
        if ($text -split "" -contains "`n" -or
            $text -split "" -contains "`r") {
            $bytes = [Byte[]] (0x0a)
        }
        if ($kc -eq 37) { $bytes = [Byte[]] (0x1b,0x5b,0x44) }  # L
        if ($kc -eq 39) { $bytes = [Byte[]] (0x1b,0x5b,0x43) }  # R
        if ($kc -eq 38) { $bytes = [Byte[]] (0x1b,0x5b,0x41) }  # U
        if ($kc -eq 40) { $bytes = [Byte[]] (0x1b,0x5b,0x42) }  # D
        if ($kc -eq 36) { $bytes = [Byte[]] (0x1b,0x5b,0x31,0x7e) }  # Home
        if ($kc -eq 35) { $bytes = [Byte[]] (0x1b,0x5b,0x34,0x7e) }  # End
        if ($kc -eq 33) { $bytes = [Byte[]] (0x1b,0x5b,0x35,0x7e,0x12) }  # PgUp
        if ($kc -eq 34) { $bytes = [Byte[]] (0x1b,0x5b,0x36,0x7e,0x12) }  # PgDn
        $stream.Write($bytes, 0, $bytes.Length)
        $stream.Flush()
        # 0x12 is ^R meaning we redraw the TUI on every scroll event
        # because powershell /usually/ can't scroll
        # (it decides to work occasionally)
    }
    Start-Sleep -Milliseconds 10
}
