#include "client.h"
#include "hdlc.h"
#include "stdio.h"
#include "stdbool.h"

#define CONNECT_FRAME_PERIOD 200
#define SIZE_DATA_BUFFER 64
#define COUNT_BUFFERS 4

bool FLAG_FILL_BUFFER1 = false;
bool FLAG_FILL_BUFFER2 = false;
bool FLAG_FILL_BUFFER3 = false;
bool FLAG_FILL_BUFFER4 = false;

#define ERR_INVALID_DATA_SIZE -1
#define ERR_ALL_BUFFERS_FILL -2

struct Client hdlc_client;

uint8_t buffer_data[COUNT_BUFFERS][SIZE_DATA_BUFFER];

struct Client init_hdlc_client(enum HDLCState *state){
    return hdlc_client;
}

void connect(struct Client* client){
    client->state = CONNECTING;
}

int send_data(struct Client* client, uint8_t* data, size_t data_len){
    if (data_len > 64){
        return ERR_INVALID_DATA_SIZE;
    }

    if (!FLAG_FILL_BUFFER1){
        for(int i = 0; i < SIZE_DATA_BUFFER; i++){
            buffer_data[0][i] = data[i];
        }

        FLAG_FILL_BUFFER1 = true;
    } else if (!FLAG_FILL_BUFFER2){
        for(int i = 0; i < SIZE_DATA_BUFFER; i++){
            buffer_data[1][i] = data[i];
        }

        FLAG_FILL_BUFFER2 = true;
    } else if (!FLAG_FILL_BUFFER3){
        for(int i = 0; i < SIZE_DATA_BUFFER; i++){
            buffer_data[2][i] = data[i];
        }

        FLAG_FILL_BUFFER3 = true;
    } if (!FLAG_FILL_BUFFER4){
        for(int i = 0; i < SIZE_DATA_BUFFER; i++){
            buffer_data[3][i] = data[i];
        }

        FLAG_FILL_BUFFER4 = true;
    } else {
        return ERR_ALL_BUFFERS_FILL;
    }

    client->state = READY_STATE;
};

int get_frame(struct Client* client, uint8_t buffer[], size_t lenBuffer){
    hdlc_control_t control_send;

    switch (client->state) {
        case CONNECTING:
            if (client->connecting_frame_timeout <= 0){
                control_send.frame = HDLC_FRAME_ACK;
                control_send.seq_no = 1;

                int ret = hdlc_frame_data(&control_send, NULL, 0, buffer, &lenBuffer);
                if (ret < 0){
                    printf("err in get_frame ACK: %d\n", ret);
                }

                client->connecting_frame_timeout = CONNECT_FRAME_PERIOD;
            }
            break;
        case READY_STATE:
            control_send.frame = HDLC_FRAME_DATA;
            control_send.seq_no = 1;
            int ret = hdlc_frame_data(&control_send, buffer_data[0], SIZE_DATA_BUFFER, buffer, &lenBuffer);
            if (ret < 0){
                printf("err in get_frame DATA: %d\n", ret);
            }
            break;
    }

//   Yf

    return 0;
}

int hdlc_get_raw_data(struct Client* client, uint8_t buffer[], size_t len_buffer){
    hdlc_control_t recv_control;
    uint8_t recive[len_buffer];

    int ret = hdlc_get_data(&recv_control, buffer, len_buffer, recive,
                            &len_buffer);
    if (ret < 0){
        printf("err in get_raw_data: %d\n", ret);
    }
    if (recv_control.frame == HDLC_FRAME_ACK){
        client->state = IDLE_STATE;
    }
    return 0;
}

void hdlc_timeout_handler(struct Client* client, int delta_time){
    client->connecting_frame_timeout -= delta_time;
}