/**
 * Timeout in milliseconds for retrieving network config.
 * If a config cannot be received within this time, the retrieval is considered failed.
 */
#define CONFIG_RETRIEVE_TIMEOUT 30000

#define ED25519_SECRETKEYBYTES 64

#define ED25519_PUBLICKEYBYTES 32

typedef struct RuntimePtr {
  void *_0;
} RuntimePtr;

typedef struct AgentConfigPtr {
  void *_0;
} AgentConfigPtr;

typedef struct NetworkInfo {
  const char *url;
  int disabled;
  const char *name;
} NetworkInfo;

typedef struct ControllerAuthState {
  int state;
  const char *display_login_email;
  const char *verification_url;
  const char *failure_message;
} ControllerAuthState;

typedef struct ControllerAuthSessionPtr {
  void *_0;
} ControllerAuthSessionPtr;

typedef struct NetworkChange {
  const char *ips;
  const char *routes;
  const char *dns_server;
  const char *routing_domains;
} NetworkChange;

typedef struct TunDevicePtr {
  void *_0;
} TunDevicePtr;

typedef struct AgentPtr {
  void *_0;
} AgentPtr;

const char *netsody_agent_version(void);

int netsody_agent_init_logging(void);

int netsody_agent_runtime(struct RuntimePtr **runtime);

void netsody_agent_runtime_free(struct RuntimePtr *runtime);

int netsody_agent_config_load_or_generate(const char *path, struct AgentConfigPtr **config);

int netsody_agent_config_id_pk(struct AgentConfigPtr *config, char *pk);

void netsody_agent_config_free(struct AgentConfigPtr *config);

int netsody_agent_config_network_add(const char *path, const char *network_url);

int netsody_agent_config_network_remove(const char *path, const char *network_url);

int netsody_agent_config_networks(const char *path, struct NetworkInfo **networks, int *count);

const char *netsody_agent_network_url(const struct NetworkInfo *networks, int index);

int netsody_agent_network_disabled(const struct NetworkInfo *networks, int index);

const char *netsody_agent_network_name(const struct NetworkInfo *networks, int index);

void netsody_agent_config_networks_free(struct NetworkInfo *networks, int count);

int netsody_agent_config_network_enable(const char *path, const char *network_url);

int netsody_agent_config_network_disable(const char *path, const char *network_url);

int netsody_agent_config_controller_auth_state(const char *config_path,
                                               struct ControllerAuthState **state);

void netsody_agent_controller_auth_state_free(struct ControllerAuthState *state);

int netsody_agent_controller_auth_session_create(const char *config_path,
                                                 const char *os_version,
                                                 struct ControllerAuthSessionPtr **session);

int netsody_agent_controller_auth_session_create_with_device_name(const char *config_path,
                                                                  const char *os_version,
                                                                  const char *device_name,
                                                                  struct ControllerAuthSessionPtr **session);

int netsody_agent_controller_auth_session_login(struct ControllerAuthSessionPtr *session,
                                                struct ControllerAuthState **state);

int netsody_agent_controller_auth_session_get_state(struct ControllerAuthSessionPtr *session,
                                                    struct ControllerAuthState **state);

int netsody_agent_controller_auth_session_sync_in_progress(struct ControllerAuthSessionPtr *session);

int netsody_agent_controller_auth_session_logout(struct ControllerAuthSessionPtr *session,
                                                 struct ControllerAuthState **state);

void netsody_agent_controller_auth_session_free(struct ControllerAuthSessionPtr *session);

void netsody_agent_string_free(char *value);

const char *netsody_agent_network_change_ips(const struct NetworkChange *change);

const char *netsody_agent_network_change_routes(const struct NetworkChange *change);

const char *netsody_agent_network_change_dns_server(const struct NetworkChange *change);

const char *netsody_agent_network_change_routing_domains(const struct NetworkChange *change);

int netsody_agent_start(struct RuntimePtr *runtime,
                        struct AgentConfigPtr *config,
                        const char *config_path,
                        struct TunDevicePtr *tun_device,
                        void (*networks_change_callback)(const struct NetworkChange *change),
                        const char *dns_servers,
                        const char *os_version,
                        struct AgentPtr **agent);

int netsody_agent_shutdown(struct RuntimePtr *runtime, struct AgentPtr *agent);

void netsody_agent_free(struct AgentPtr *agent);

int netsody_agent_tun_device_create(struct RuntimePtr *runtime,
                                    int fd,
                                    struct TunDevicePtr **tun_device);

void netsody_agent_tun_device_free(struct TunDevicePtr *tun_device);

int netsody_agent_update_tun_device(struct RuntimePtr *runtime,
                                    struct AgentPtr *agent,
                                    struct TunDevicePtr *new_tun_device);

char *netsody_agent_status(struct RuntimePtr *_runtime, struct AgentPtr *agent);

char *netsody_agent_network_details_json(struct RuntimePtr *runtime,
                                         struct AgentPtr *agent,
                                         const char *network_url);
