/**
 * @file UDP_broadcast.h
 *
 * @brief UDP broadcast handler
 *  Created on: Nov 6, 2023
 *      Author: joran
 */

#ifndef INC_UDP_BROADCAST_H_
#define INC_UDP_BROADCAST_H_

// includes
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "lwip.h"
#include "lwip/netif.h"
#include "udp.h"

#include "lcd_api.h"

// Defines used by UDP callback
#define UDP_BROADCAST_MAX_DATA_SIZE ((UDP_BROADCAST_MAX_NAME_SIZE * 2) - 2 + 25)    // Define the maximum expected data size
#define UDP_BROADCAST_UDP_QUESTION1 "Where are you?v1.0"                            // Expected question from UDP client
#define UDP_BROADCAST_MAX_FUNC_LEN 7
#define UDP_BROADCAST_MAX_COLON_COMMA_COUNT 4

// Defines used by owner details
#define UDP_BROADCAST_MAX_REPLY_SIZE (UDP_BROADCAST_MAX_MAC_ADDR_LEN + sizeof(UDP_BROADCAST_REPLY_MIDDLE_TEXT) + (UDP_BROADCAST_MAX_NAME_SIZE * 2) + UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA)
#define UDP_BROADCAST_REPLY_MIDDLE_TEXT "is present and my owner is"

#define UDP_BROADCAST_MAX_MAC_ADDR_LEN 19       // Format is: "xx:xx:xx:xx:xx:xx"
#define UDP_BROADCAST_MAX_NAME_SIZE 21          // Code automatically leaves 1 char for '\0' (actual length = length - 1)
#define UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA 20   // Just a bit extra

#define UDP_BROADCAST_LCD_NAME_PRE_TEXT "New owner: "
#define UDP_BROADCAST_LCD_TEXT_SIZE (strlen(UDP_BROADCAST_LCD_NAME_PRE_TEXT) + UDP_BROADCAST_MAX_NAME_SIZE)


/**
 * @struct owner_details_t
 * @brief contains information about the owner
 *
 */

typedef struct {
    char name[UDP_BROADCAST_MAX_NAME_SIZE];
    char surname[UDP_BROADCAST_MAX_NAME_SIZE];
    uint8_t mac_address[6];
    char reply[UDP_BROADCAST_MAX_REPLY_SIZE];
} owner_details_t;

// The following functions are used for owner details (those that must be available in main)

/**
 * @fn err_t udp_broadcast_set_owner_details(const char*, const char*)
 * @brief udp_broadcast_set_owner_details() is the interface that can be used in other files
 * to set the owner's details
 *
 * @param[in] name string containing the new owner's name
 * @param[in] surname string containing the new owner's surname
 * @return lwIP error code.
 * - ERR_OK. Successful. No error occurred.
 * - ERR_ARG. one or both arguments are NULL pointers
 */
err_t udp_broadcast_set_owner_details(const char*, const char*);

/**
 * @fn char udp_broadcast_get_owner_details_name*(void)
 * @brief udp_broadcast_get_owner_details_name() can be used to get the current owner's name
 *
 * @return name of owner
 * this name is set by @see udp_broadcast_set_owner_details_name()
 */
char* udp_broadcast_get_owner_details_name(void);

/**
 * @fn char udp_broadcast_get_owner_details_surname*(void)
 * @brief udp_broadcast_get_owner_details_surname() can be used to get the current owner's surname
 *
 * @return surname of owner
 * this name is set by @see udp_broadcast_set_owner_details_surname()
 */
char* udp_broadcast_get_owner_details_surname(void);

/**
 * @fn char udp_broadcast_get_owner_details_reply*(void)
 * @brief udp_broadcast_get_owner_details_reply() can be used to get the current UDP reply
 *
 * @return reply for UDP broadcast
 * this reply is formatted by @see format_reply()
 */
char* udp_broadcast_get_owner_details_reply(void);

// Initialization functions

/**
 * @fn err_t udp_broadcast_init(uint16_t x_pos, uint16_t y_pos)
 * @brief udp_broadcast_init() initializes the owner's variables and calls upon @see udp_broadcast_connection_init()
 *
 * @param[in] x_pos : uint16_t that sets the x coordinate the owner's name will be written on the LCD
 * @param[in] y_pos : uint16_t that sets the y coordinate the owner's name will be written on the LCD
 * @return lwIP error code.
 * - ERR_OK. Successful. No error occurred.
 * - ERR_USE. The specified ipaddr and port are already bound to by another UDP PCB.
 * - ERR_MEM. udp pcb couldn't be created
 *
 * - ERR_ARG. one or both arguments of udp_broadcast_set_owner_details() are NULL pointers
 */

err_t udp_broadcast_init(uint16_t x_pos, uint16_t y_pos);

/**
 * @fn err_t udp_broadcast_connection_init()
 * @brief udp_broadcast_connection_init() initializes the UDP connection so that it listens for all traffic on
 * port 6400
 * it is called by @see udp_broadcast_init() aswell but can be used separately if it failed before
 *
 * @return lwIP error code.
 * - ERR_OK. Successful. No error occurred.
 * - ERR_USE. The specified ipaddr and port are already bound to by another UDP PCB.
 * - ERR_MEM. udp pcb couldn't be created
 */

err_t udp_broadcast_connection_init(void);

#endif /* INC_UDP_BROADCAST_H_ */
