#include <zephyr.h>
#include <net/socket.h>
#include <lte_lc.h>

#include <SEGGER_RTT.h>

static uint8_t rtt_buf[1024];
static uint8_t recv_buf[1024];

#ifdef CONFIG_BSD_LIBRARY

void bsd_recoverable_error_handler(uint32_t err)
{
    printk("bsdlib recoverable error: %u\n", err);
}

void bsd_irrecoverable_error_handler(uint32_t err)
{
    printk("bsdlib irrecoverable error: %u\n", err);

    __ASSERT_NO_MSG(false);
}

#endif

void main(void)
{
    int err;

    printk("tcp_client sample\n");
    printk("Configuring RTT up buffer 1 ... ");
    SEGGER_RTT_ConfigUpBuffer(1, "File", rtt_buf, sizeof(rtt_buf), SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
    printk("done.\n");

    printk("LTE Link Connecting ...\n");
    err = lte_lc_init_and_connect();
    __ASSERT(err == 0, "LTE link could not be established.");
    printk("LTE Link Connected!\n");

    struct addrinfo *res;
    struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM};

    err = getaddrinfo(CONFIG_TCP_SERVER_HOST, NULL, &hints, &res);
    __ASSERT(err == 0, "Server hostname could not be resolved, err=%d, errno=%d", err, errno);
    ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(CONFIG_TCP_SERVER_PORT);

    int client_fd;

    for(int i=0; i<16; i++)
    {
        client_fd = socket(AF_INET, SOCK_STREAM, 0);
        printk("client_fd: %d\n\r", client_fd);

        err = connect(client_fd, (struct sockaddr *)res->ai_addr, sizeof(struct sockaddr_in));
        if (err==0)
        {
            break;
        }
        err = close(client_fd);
        printk("Attempt %d: could not connect to server, err=%d, errno=%d\n", i, err, errno);
        k_sleep(1000*i*i); //simple exponential back-off
    }
    __ASSERT(err == 0, "Error, could not connect to server, err=%d, errno=%d", err, errno);
    printk("Connected to server.\n");

    int ret;
    int total_rx_bytes = 0;
    while(1)
    {
        ret = recv(client_fd, recv_buf, sizeof(recv_buf), 0);
        if (ret > 0)
        {
            total_rx_bytes += ret;
            printk("Rx %d bytes, total=%d\n", ret, total_rx_bytes);
            SEGGER_RTT_Write(1, recv_buf, ret);
        }
        else if (ret < 0 && errno == EAGAIN)
        {
            printk("EAGAIN\n");
        }
        else
        {
            printk("Unhandled error, ret=%d, errno=%d\n", ret, errno);
            break;
        }
        k_sleep(4000); //<-- seems to be the culprit for lost data :(
    }

    printk("Closing socket ... ");
    err = close(client_fd);
    __ASSERT(err == 0, "Could not close socket, err=%d.", err);
    printk("goodbye.\n");
}
