/*
 Simple udp server
 */
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include "driver/uart.h"

#include "UDP_rec.h"

#define PORT 65432   //should be 9761 for rs232 The port on which to listen for incoming data

#define ECHO_TEST_TXD  (GPIO_NUM_4)
#define ECHO_TEST_RXD  (GPIO_NUM_5)
#define ECHO_TEST_RTS  (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS  (UART_PIN_NO_CHANGE)

#define BUF_SIZE (512)

bool dataReady;

void udp_task(void *pvParameters) {
	bool remote_acquired;
	uint8_t *data = (uint8_t*) malloc(BUF_SIZE);
	static int s;
	memset(data, 0x00, BUF_SIZE);

	static struct sockaddr_in si_me, si_other, si_copy;
	int recv_len = -1;
	uint32_t slen = sizeof(si_other);
	/* Configure parameters of an UART driver,
	 * communication pins and install the driver */
	uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE,
			.stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE };
	uart_param_config(UART_NUM_1, &uart_config);
	uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS,
	ECHO_TEST_CTS);

	// install uart driver
	uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);

	struct timeval read_timeout;
	read_timeout.tv_sec = 0;
	read_timeout.tv_usec = 100;
	memset(data, 0x00, BUF_SIZE);

	dataReady = false;
	remote_acquired = false;
	s = -1;

	while (1) {
		if (s == -1) {
			//create a UDP socket
			if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1) {

				// zero out the structure
				memset((char *) &si_me, 0, sizeof(si_me));

				//int err = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*) &read_timeout, sizeof read_timeout);

				int err = setsockopt(s, IPPROTO_UDP, SO_RCVTIMEO, (char*) &read_timeout, sizeof read_timeout);
				if (err < 0) {
					printf("Socket opt fail %d \r\n", err);
				}
				si_me.sin_family = AF_INET;
				si_me.sin_port = htons(PORT);
				si_me.sin_addr.s_addr = htonl(INADDR_ANY);

				//bind socket to port
				if (bind(s, (struct sockaddr*) &si_me, sizeof(si_me)) == -1) {
					close(s);
					perror("not bind error");
					s = -1;
				}

			}

			printf("starting...\r\n");
		}
		recv_len = -1;

		if ((dataReady) && (remote_acquired)) {
			// send new data if remote has been in touch.
			memcpy(data, &new_data, 30);
			if (sendto(s, data, 30, 0, (struct sockaddr*) &si_other, slen) == -1) {
				perror("sendto()");
				return;
			}
			dataReady = false;
			printf("Sent data...\r\n");

		} else {
			recv_len = recvfrom(s, data, BUF_SIZE, 0, (struct sockaddr *) &si_other, &slen);
			if (recv_len != -1) {
				// we have data
				//print details of the client/peer and the data received
				//copy sremote details to send routine

				printf("Received packet from %s:%d\r\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
				printf("Data: %s\n", data);
				uart_write_bytes(UART_NUM_1, (const char *) data, recv_len);
				memset(data, 0x00, BUF_SIZE);
				memcpy(data, "ACK\r\n", 5);
				remote_acquired = true;
				if (sendto(s, data, 5, 0, (struct sockaddr*) &si_other, slen) == -1) {
					perror("sendto()");
					return;
				}
			}

		}
		vTaskDelay(1000 / portTICK_PERIOD_MS);
		printf("Finished...\r\n");
	}

	close(s);
	vTaskDelete( NULL);
}

void setDataReady() {

	memcpy((void*) &new_data, "This is test data to be sent\r\n", 30);
	dataReady = true;

}

