#ifndef NCODE_NET_GEN_H
#define NCODE_NET_GEN_H

#include <chrono>
#include <cstdint>
#include <random>
#include <vector>

#include "net_common.h"

namespace nc {
namespace net {

// Generates a topology similar to HE's backbone. The topology will have 31
// devices and 56 bidirectional links. All links in the network will have a
// delay of max(1, d * delay_multiply + delay_add) where d is the speed of light
// in fiber delay.
GraphBuilder GenerateHE(Bandwidth bw, Delay delay_add = Delay(0),
                        double delay_multiply = 1.0);

// Generates a topology similar to NTT's backbone. Unlike HE above this function
// will also populate real-world bandiwdth values.
GraphBuilder GenerateNTT(Delay delay_add = Delay(0),
                         double delay_multiply = 1.0,
                         Bandwidth bw_add = Bandwidth::FromBitsPerSecond(0),
                         double bw_multiply = 1.0);

// Generates a full graph of a given size. Each node will be named Ni for i in
// [0, size).
GraphBuilder GenerateFullGraph(uint32_t size, Bandwidth bw, Delay delay);

// Generates a ladder-like topology. All links have the same rate and delay.
// Nodes will be named Ni for i in [0, ...]. Odd nodes will be on one side
// of the ladder, even nodes will be on the other. The middle links will have
// their capacity multiplied by the central_rate_multiplier argument. If the
// central_delays argument is not empty it should contain as many elements as
// levels. Each element will be the delay of the middle connecting link for the
// respective level. With 1 level this is a line, 2 levels a hexagon, 3 levels
// two hexagons attached etc.
GraphBuilder GenerateLadder(size_t levels, Bandwidth rate_bps, Delay delay,
                            double central_rate_multiplier = 1.0,
                            const std::vector<Delay>& central_delays = {});

// Generates a random graph with N nodes. Each of the n * (n - 1) edges has a
// uniform probability of edge_prob of being part of the graph. If this is set
// to 1.0 the graph will be a full graph. Each edge's delay and bandwidth will
// be picked at uniform from the given ranges. Nodes will be named Ni for i in
// [0, N).
GraphBuilder GenerateRandom(size_t n, double edge_prob, Delay delay_min,
                            Delay delay_max, Bandwidth bw_bps_min,
                            Bandwidth bw_bps_max, std::mt19937* generator);

// A simple Braess paradox-like topology used for testing.
GraphBuilder GenerateBraess(Bandwidth bw);

// Loads a topology in the format used by
// https://bitbucket.org/StevenGay/repetita/src. The first line of the file is
// "NODES XX" followed by a comment line and XX lines for each of the nodes in
// the graph. Each node line is of the format <node_name> <x> <y> where x and y
// are the x,y coordinates of the node. The nodes section is followed by and
// empty line and "EDGES XX" on a new line. A comment line is next, followed by
// for each edge "<label> <src> <dst> <weight> <bw> <delay>". The bandwidth is
// in kbps and the delay in microseconds. If the 'node_order' parameter is
// supplied, will populate it with the nodes from the graph in the same order in
// which they appear in the topology string.
GraphBuilder LoadRepetitaOrDie(
    const std::string& topology_string,
    std::vector<std::string>* node_order = nullptr,
    std::map<std::string, std::pair<double, double>>* locations = nullptr);

}  // namespace net
}  // namespace ncode
#endif
