#! raku

use v6.d;

use Protocol::Postgres;

unit sub MAIN(Str :$user = ~$*USER, Str :$database = 'test', Str :$password, :$host = 'localhost', :$port = 5432);

my $socket = await IO::Socket::Async.connect($host, $port);
my $client = Protocol::Postgres::Client.new;
$socket.Supply(:bin).act({ $client.incoming-data($^data) }, :done({ $client.disconnected.keep }), :quit({ $client.disconnected.break($^reason) }));
$client.outbound-data.act({ await $socket.write($^data) }, :done({ $socket.close }));

await $client.startup($user, $database, $password);

sub io-supply(IO::Handle $handle) {
	my $supplier = Supplier.new;
	start {
		for $handle.lines -> $line {
			$supplier.emit($line);
		}
		$supplier.done;
	}
	return $supplier.Supply;
}

react {
	whenever io-supply($*IN) {
		when / ^ '\\'? q[uit]? / {
			$client.terminate;
		}
		when / ^ p['arameter ']? $<parameter>=[\w+] / {
			say $client.get-parameter(~$<parameter>);
		}
		default {
			CATCH { default { say .message } }
			given await $client.query(~$_) {
				when Protocol::Postgres::ResultSet {
					react {
						whenever .hash-rows -> $row {
							dd $row;
						}
					}
				}
				when Str {
					say $_;
				}
				when Supply {
					for $_.list -> $row {
						say $row.chomp;
					}
				}
				when Supplier {
					my $supplier = $_;
					for lines() -> $line {
						last if $line eq "";
						$supplier.emit("$line\n");
					}
					$supplier.done;
				}
			}
		}
	}
	whenever $client.disconnected {
		done;
	}
}
