#include <ehs/Str.h>
#include <ehs/Version.h>
#include <ehs/io/Window.h>
#include <ehs/io/socket/ICMP.h>
#include <ehs/io/socket/DNS.h>
#include <ehs/io/Console.h>

using namespace ehs;

int main()
{
	Initialize("Test", "Release", {1, 0, 0});
	Log::EnableImmediateMode(true);

	Serializer<UInt_64> payload(Endianness::LE);
	payload.WriteStr("Hello, world!");

	ICMP icmp(IP::V6);

	Console::Write_8("Remote IPv6: ", false);
	Str_8 remote = Console::Read_8();

	Console::Write_8("ID: ", false);
	UInt_16 id = Console::Read_8().ToDecimal<UInt_16>();

	Console::Write_8("Sequences: ", false);
	UInt_16 sequences = Console::Read_8().ToDecimal<UInt_16>();

	for (UInt_16 i = 1; i <= sequences; ++i)
		icmp.SendEchoRequest(DNS::Resolve(IP::V6, remote), {id, i}, payload, payload.Size());

	ICMP_Header icmpHeader;
	ICMP_EchoRequest echoRequest;

	for (UInt_16 i = 1; i <= sequences; ++i)
	{
		do
		{
			payload = Serializer<UInt_64>(Endianness::LE);

			icmp.Receive(remote, icmpHeader, payload);

			echoRequest = payload.Read<ICMP_EchoRequest>();
		}
		while (icmpHeader.type != 129 || echoRequest.id != id);

		Console::Write_8("\nRemote: " + remote);
		Console::Write_8("Type: " + Str_8::FromNum(icmpHeader.type));
		Console::Write_8("Code: " + Str_8::FromNum(icmpHeader.code));
		Console::Write_8("Checksum: " + Str_8::FromNum(icmpHeader.checksum));

		Console::Write_8("ID: " + Str_8::FromNum(echoRequest.id));
		Console::Write_8("Sequence: " + Str_8::FromNum(echoRequest.sequence));

		Console::Write_8("Payload: " + payload.ReadStr<Char_8>());
	}

	Uninitialize();

	return 0;
}