#ifndef __PRSONA_NETWORK_ORCHESTRATOR_HPP
#define __PRSONA_NETWORK_ORCHESTRATOR_HPP

#include <string>
#include <vector>
#include <chrono>

#include "networking.hpp"

const std::chrono::seconds TWO_SECONDS(2);
const std::chrono::seconds ONE_SECOND(1);
const std::chrono::milliseconds HALF_SECOND(500);

/* "PUBLIC" FUNCTIONS */

// START UP AND SHUT DOWN INSTANCES
void start_remote_actor(
    const std::string& target,
    bool server,
    const std::string& id,
    const std::string& output,
    size_t lambda,
    bool maliciousServers);

void shut_down_remote_actors(
    const std::vector<std::string>& relevantIPs,
    const std::vector<int>& relevantPorts);

// SYNCHRONIZATION
void wait_for_servers_ready(
    std::string dealer,
    int dealerPort);

void wait_for_clients_created(
    std::string dealer,
    int dealerPort,
    size_t numClients);

void wait_for_client_ready(
    std::string client,
    int clientPort);

// RUN EXPERIMENT
void execute_experiment(
    std::default_random_engine& rng,
    std::string dealerIP,
    int dealerPort,
    std::vector<std::string> serverIPs,
    std::vector<int> serverPorts,
    std::vector<std::string> clientIPs,
    std::vector<int> clientPorts,
    const char *filename);

/* "PRIVATE" FUNCTIONS */

// TRIGGER EXPERIMENT EVENTS
void trigger_epoch_change(
    std::string dealer,
    int dealerPort);

void trigger_vote(
    std::string target,
    int targetPort);

void trigger_reputation_proof(
    std::string target,
    int targetPort,
    std::string verifier,
    int verifierPort);

// EXECUTOR HELPER

std::vector<size_t> generate_random_set(
    std::default_random_engine& rng,
    size_t size,
    size_t maxVal);

#endif
