#pragma once 
#include "endian.hpp"
#include "database.hpp"

/*************************************/
/*          STORAGE SERVER           */
/*************************************/

enum class db_op : uint32_t {
	version = 0,
	read = 1,
	write = 2,
	remove = 3,
	stats = 4,
	sread = 5,
	swrite = (2 << 16) + write,
	sallocate = 7,
	sremove = (2 << 16) + remove,
	confirm = 8,
	bulk_write = (2 << 15) + write
};

struct [[gnu::packed]] received_data {
	bitops::regulated<db_op> op = db_op::version;
	bitops::regulated<uint64_t> rep_id = 0;
	record_identifier identifier = record_identifier{};
	db_page page = {0};
};

struct [[gnu::packed]] received_bulk_data {
	bitops::regulated<db_op> op = db_op::version;
	bitops::regulated<uint64_t> rep_id = 0;
	bitops::regulated<uint32_t> nb_count = 0;
	std::array<record_identifier, 4096/sizeof(record_identifier)> identifiers;
	std::array<db_page, 4096/sizeof(record_identifier)> page;
};

struct [[gnu::packed]] sending_data {
	bitops::regulated<uint64_t> rep_id = 0;
	record identifier = record{};
	db_page page = {0};
};

struct [[gnu::packed]] stats_data {
	bitops::regulated<uint64_t> free;
	bitops::regulated<uint64_t> free_deleted;
	bitops::regulated<uint64_t> total_pages;
	bitops::regulated<uint64_t> total_records;
	bitops::regulated<uint64_t> total_delete;
	bitops::regulated<uint64_t> cow_full;
	bitops::regulated<uint64_t> free_records;
	bitops::regulated<uint64_t> sync_rate_µs;
	bitops::regulated<uint64_t> sync_duration_µs;
	bitops::regulated<uint64_t> max_sync_duration_µs;
	bitops::regulated<uint64_t> avg_sync_duration_µs;
};

/*************************************/
/*         COORDINATE SERVER         */
/*************************************/


enum class coord_op : uint32_t {
	version = 0,
	read = 1,
	write = 2,
	remove = 3,
	stats = 4
};


struct [[gnu::packed]] received_data_coord {
	bitops::regulated<db_op> op = db_op::version;
	bitops::regulated<uint64_t> rep_id = 0;
	record_identifier identifier = record_identifier{};
	db_page pageA = {0};
	db_page pageB = {0};
};

struct req_rep {
	uint64_t id = 0;
	uint64_t client_ts = 0;
	bitops::regulated<uint64_t> server_ts = 0;
};