#include <iostream>
#include <fstream>
#include <sstream>
#include <variant>
#include <chrono>
#include <algorithm>
#include "database.hpp"
#include "network.hpp"
#include <memory>
#include <cstdlib> 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include "commander.hpp"


int main(int argc, char** argv)
{
	try{
		while(argc == 3)
		{
			std::stringstream ip_stream{argv[1]};
			std::array<uint8_t, 4> ip;
			std::string token;
			std::getline(ip_stream, token, '.');
			ip[0] = std::stoi(token);
			std::getline(ip_stream, token, '.');
			ip[1] = std::stoi(token);
			std::getline(ip_stream, token, '.');
			ip[2] = std::stoi(token);
			std::getline(ip_stream, token, '.');
			ip[3] = std::stoi(token);

			uint16_t port = std::stoi(argv[2]);


			auto soc = socket(AF_INET, SOCK_DGRAM, 0);
			struct sockaddr_in server;
			server.sin_family = AF_INET;
			server.sin_addr.s_addr = *(in_addr_t*)ip.data();
			server.sin_port = htons(port);

			connect(soc, (struct sockaddr*)&server, sizeof(server));

			
			sending_data reply;
			received_data request;

			request.op = db_op::stats;

			send(soc, (void*)&request, (socklen_t)sizeof(request), 0);
			recv(soc, (void*)&reply, (socklen_t)sizeof(reply), 0);

			auto stats = (stats_data*)&reply.page;

			std::cout << "free_pages\t" << stats->free << std::endl;
			std::cout << "deleted_pages\t" << stats->free_deleted << std::endl;
			std::cout << "total_pages\t" << stats->total_pages << std::endl;
			std::cout << "usable_records\t" << stats->free_records << std::endl;
			std::cout << "total_records\t" << stats->total_records << std::endl;
			std::cout << "delete_cache\t" << stats->total_delete << std::endl;
			std::cout << "inaccessible\t" << stats->cow_full << std::endl;
			std::cout << "sync_rate\t" << stats->sync_rate_µs << "µs (" << stats->sync_rate_µs/1000000.0f << "s)" << std::endl;
			std::cout << "sync_durr\t" << stats->sync_duration_µs << "µs (" << stats->sync_duration_µs/1000000.0f << "s)" << std::endl;
			std::cout << "max_sync_durr\t" << stats->max_sync_duration_µs << "µs (" << stats->max_sync_duration_µs/1000000.0f << "s)" << std::endl;
			std::cout << "avg_sync_durr\t" << stats->avg_sync_duration_µs << "µs (" << stats->avg_sync_duration_µs/1000000.0f << "s)" << std::endl;

			return 0;
		}
	}catch(...) {
		exit(13);
	}
	std::cerr << "Invalid command, expects ``db_stats IPV4 PORT''" << std::endl;
	return 1;
}