// ॐ सूक्ष्म शरीर
#ifndef SLEEP_H
#define SLEEP_H
// TODO implement SLEEP
/*metadata.key
metadata.signatures
metadata.bitfield
metadata.tree
metadata.data
content.key
content.signatures
content.bitfield
content.tree*/
#include "key.h"
#include <stdint.h>
#include <stddef.h>
// test
#include <assert.h>

#ifdef __cplusplus
extern "C" {
#endif

#define SLEEP_HEADER_SIZE	32u

// TODO MAGIC_BITFIELD, MAGIC_SIG, MAGIC_TREE

#define SLEEP_ALGO_BLAKE2B	"BLAKE2b"
#define SLEEP_ALGO_ED25519	"Ed25519"

#define SLEEP_TREE_ENTRY_SIZE	40u
#define SLEEP_SIG_ENTRY_SIZE	64u
#define SLEEP_BITFIELD_ENTRY_SIZE 3328u

enum sleep_hash_type {
	SLEEP_HASH_LEAF	= 0,
	SLEEP_HASH_PARENT	= 1,
	SLEEP_HASH_ROOT	= 2
};

// Wire
#if defined(__GNUC__) || defined(__clang__) || defined(__MUSL__)
	#define SLEEP_PACKED __attribute__((packed))
#else
	#define SLEEP_PACKED
	#pragma pack(push,1) // pragma deez
#endif


typedef struct SLEEP_PACKED sleep_header {
	uint32_t	magic_be;
	uint8_t	version;
	uint16_t	entry_size_be;
	uint8_t	algo_len;
	char	algo[24];
} sleep_header_t;
// TODO assert must be 32 bytes

// 32 byte hash + 8 byte BE len
typedef struct SLEEP_PACKED sleep_tree_entry {
	uint8_t hash[32];
	uint64_t length_be;
} sleep_tree_entry_t;
// TODO assert

// 64 bytes
typedef struct SLEEP_PACKED sleep_sig_entry {
	uint8_t sig[64];
} sleep_sig_entry_t;
// TODO assert

// 3328 bytes: tree[2048] + data[1024] + index[256]
typedef struct SLEEP_PACKED sleep_bitfield_entry {
	uint8_t tree[2048];
	uint8_t data[1024];
	uint8_t index[256];
} sleep_bitfield_entry_t;
// TODO DOTO ODOT assert it

#if !defined(__GNUC__) && !defined(__clang__)
  #pragma pack(pop)
#endif

// TODO BE INT into and out of buffers **

// crypto helpers
#ifdef SLEEP_SALT
int sleep_gen_ed25519(uint8_t pubkey[32], uint8_t seckey[64]);
// sign
int sleep_sign_ed25519(const uint8_t *msg, size_t msglen,
		       const uint8_t seckey[64], uint8_t sig_out[64]);
// verify
int sleep_verify_ed25519(const uint8_t *msg, size_t msglen,
			 const uint8_t pubkey[32], const uint8_t sig[64]);
// discovery
int sleep_compute_discovery_key(const uint8_t pubkey[32], uint8_t out32[32]);
#endif /* SLEEP_SALT */

// function decs

#ifdef __cplusplus
}
#endif
#endif /* SLEEP_H */
