#pragma once
#include <stdint.h>
#include <strings.h>

#include "protocol.hpp"

#define MAX_PAGE_SIZES 4*7

enum FrameSubmitionResult {
    PENDING,
    COMPLEATE,
    ERROR_INVALID_RPC_TYPE,
    ERROR_INVALID_RPC_NUMBER,
    ERROR_NO_EMPTY_OR_FITTING_SLOT,
};

struct RPC_RX_PackageSlot {
    char buffer[MAX_PAGE_SIZES];

    bool is_complete;
    bool is_in_use;

    uint32_t sender_address;
    enum RPCNumber rpcNum;
    enum RPCType type;
    uint32_t used_bit_masked;
    uint32_t timestamp;
    size_t length;
};

struct RPCPackage {
    char buffer[MAX_PAGE_SIZES];
    size_t length;
    uint32_t addr;
    RPCNumber rpcNum;
    RPCType type;
};

#define NUM_SLOTS 8

class GobotRPCParser {
private:
    RPC_RX_PackageSlot buffer[NUM_SLOTS];
    uint32_t masked [NUM_SLOTS];
    uint32_t address_mask;

    size_t finishedScanIndex;

    void find_fitting_slot(RPCHeader header, uint32_t addr, int * fitting_slot, int * empty_slot);
    static void insertFrameInPackageSlot(RPC_RX_PackageSlot * package, char * data, size_t segment, size_t length);
    void freePackageSlot(size_t index);

public: 
    GobotRPCParser();

    void print_out_slots();
    enum FrameSubmitionResult submit_frame(char * data, size_t length, uint32_t addr, uint32_t timestamp);
    
    int getFinishedIndexPackages();
    void retrivePackage(RPCPackage * dest, int index);
};

char * mapFrameSubmitionResult2String(FrameSubmitionResult res);

FrameSubmitionResult getPackageStatus(RPC_RX_PackageSlot * package);
