#ifndef CWDAEMON_TESTS_LIB_SERVER_H
#define CWDAEMON_TESTS_LIB_SERVER_H




#include <arpa/inet.h>
#include <stdbool.h>
#include <sys/types.h> /* pid_t */

#include <libcw.h>

#include "client.h"
#include "cwdevice_observer.h"
#include "events.h"
#include "supervisor.h"




/* For now this structure doesn't allow for usage and tests of remote
   cwdaemon server. */
typedef struct server_t {
	pid_t pid;    /**< pid of local test instance of cwdaemon process. */
	int wstatus;  /**< Second argument to waitpid(). */

	/// @brief String representation of server's IP address.
	//
	// TODO (acerion) 2024.04.19: do we want to be able to use here a domain name?
	char ip_address[INET_ADDRSTRLEN];

	/// @brief Network port, on which cwdaemon server is available and listening
	//
	// TODO (acerion) 2024.03.22: why this is int instead of in_port_t?
	int l4_port;

	/** Reference to test's events container. Used to collect events
	    registered during test that are relevant to cwdaemon server. */
	events_t * events;

	/** Type of supervisor the local instance of cwdaemon process is running
	    under. */
	supervisor_id_t supervisor_id;
} server_t;




// TODO (acerion) 2024.04.19: this size should be defined in cwdaemon.h.
// See also comment for CWDEVICE_PATH_SIZE.
#define CWDEVICE_NAME_SIZE 16

typedef struct {
	int tone;       /**< [Hz] Frequency of sound generated by cwdaemon server. */
	enum cw_audio_systems sound_system;

	/// Opposite of cwdaemon's nofork (-n, --nofork). Zero/false value of "do
	/// fork" is a common default for tests.
	bool do_fork;

	char cwdevice_name[CWDEVICE_NAME_SIZE];  /* Name of a device in /dev/. The name does not include "/dev/" */
	int wpm;
	tty_pins_t tty_pins; /**< Configuration of pins of tty port to be used as cwdevice by cwdaemon. */

	//// @brief IP address of machine where cwdaemon is available.
	///
	/// If empty, local IP will be used.
	//
	// TODO (acerion) 2024.04.19: do we want to be able to use here a domain name?
	char l3_address[INET_ADDRSTRLEN];

	/**
	   Layer 4 UDP port on which cwdaemon is listening. Passed to cwdaemon
	   through @c -p / @c --port command line option.

	   - -1: use zero as port number passed to cwdaemon (dirty special case
	        to test handling of invalid port number);
	   - 0: use random port when starting cwdaemon;
	   - positive value: use given port value when starting cwdaemon;

	   I'm using zero to signify random port, because this should be the
	   default testing method: to run a cwdaemon with any valid port number,
	   and zero is the easiest value to assign to this field.

	   I'm using @c int type instead of @c in_port_t type to allow testing
	   situations where an invalid port number (e.g. 65536) is passed to
	   cwdaemon. @c in_port_t type would not allow that value.
	*/
	int l4_port;

	/** Type of supervisor the local instance of cwdaemon process is running
	    under. */
	supervisor_id_t supervisor_id;

	/// syslog's LOG_ERR and related constants. Leave as zero to not pass
	/// command line option to started server.
	int log_threshold;
} server_options_t;




/**
   @brief Start instance of cwdaemon server

   Currently the functional tests only deal with local test instance of
   cwdaemon server, so this function is starting a local cwdaemon process.

   @reviewed_on{2024.04.20}

   @param[in] server_opts cwdaemon's configuration options
   @param[out] server Representation of started server instance

   @return 0 on success
   @return -1 on failure
*/
int server_start(server_options_t const * server_opts, server_t * server);




/**
   @brief Stop the local test instance of cwdaemon

   This is just a wrapper over local_server_stop_fuzz() with @c do_fuzz
   argument set to @c false.

   @reviewed_on{2024.04.20}

   @param server Local server to be stopped
   @param client Client instance to use to communicate with the server

   @return 0 on success
   @return -1 on failure
*/
int local_server_stop(server_t * server, client_t * client);




/**
   @brief Stop the local test instance of cwdaemon - a variant that allows fuzzing

   Set @p do_fuzz to @c true if you want to fuzz cwdaemon while sending EXIT
   escape request.

   @reviewed_on{2024.04.20}

   @param server Local server to be stopped
   @param client Client instance to use to communicate with the server
   @param[in] do_fuzz Whether to try to fuzz cwdaemon by sending random bytes together with the EXIT escape request

   @return 0 on success
   @return -1 on failure
*/
int local_server_stop_fuzz(server_t * server, client_t * client, bool do_fuzz);




#endif /* #ifndef CWDAEMON_TESTS_LIB_SERVER_H */


