#!/usr/bin/env python

# An example script using the rumba package
from rumba.model import *

# import testbed plugins
import rumba.testbeds.jfed as jfed

# import prototype plugins
import rumba.prototypes.ouroboros as our

import rumba.log as log

from rumba.storyboard import *

from rumba.utils import *

import argparse
import time

log.set_logging_level('DEBUG')

n1 = UnicastLayer("n1")

n1.add_policy("routing", "lfa")
n1.add_policy("pff", "alternate")

e1 = EthDixLayer("e1")
e2 = EthDixLayer("e2")
e3 = EthDixLayer("e3")
e4 = EthDixLayer("e4")
e5 = EthDixLayer("e5")
e6 = EthDixLayer("e6")
e7 = EthDixLayer("e7")
e8 = EthDixLayer("e8")
e9 = EthDixLayer("e9")
e10 = EthDixLayer("e10")
e11 = EthDixLayer("e11")
e12 = EthDixLayer("e12")
e13 = EthDixLayer("e13")
e14 = EthDixLayer("e14")
e15 = EthDixLayer("e15")
e16 = EthDixLayer("e16")
e17 = EthDixLayer("e17")
e18 = EthDixLayer("e18")
e19 = EthDixLayer("e19")
e20 = EthDixLayer("e20")
e21 = EthDixLayer("e21")
e22 = EthDixLayer("e22")
e23 = EthDixLayer("e23")
e24 = EthDixLayer("e24")
e25 = EthDixLayer("e25")
e26 = EthDixLayer("e26")
e27 = EthDixLayer("e27")
e28 = EthDixLayer("e28")
e29 = EthDixLayer("e29")
e30 = EthDixLayer("e30")
e31 = EthDixLayer("e31")
e32 = EthDixLayer("e32")
e33 = EthDixLayer("e33")
e34 = EthDixLayer("e34")
e35 = EthDixLayer("e35")
e36 = EthDixLayer("e36")
e37 = EthDixLayer("e37")
e38 = EthDixLayer("e38")
e39 = EthDixLayer("e39")
e40 = EthDixLayer("e40")
e41 = EthDixLayer("e41")
e42 = EthDixLayer("e42")
e43 = EthDixLayer("e43")
e44 = EthDixLayer("e44")

layers = [e1, e2, e3, e4, e5, e6, e7, e8, e9, e10,
          e11, e12, e13, e14, e15, e16, e17, e18, e19, e20,
          e21, e22, e23, e24, e25, e26, e27, e28, e29, e30,
          e31, e32, e33, e34, e35, e36, e37, e38, e39, e40,
          e41, e42, e43, e44]

lisbon = Node("lisbon",
         layers = [n1, e1, e2],
         registrations = {n1: [e1,e2]})

madrid = Node("madrid",
         layers = [n1, e1, e6, e9, e11],
         registrations = {n1 : [e1, e6, e9, e11]})

london = Node("london",
         layers = [n1, e2, e3, e4, e5],
         registrations = {n1 : [e2, e3, e4, e5]})

dublin = Node("dublin",
         layers = [n1, e3],
         registrations = {n1 : [e3]})

paris = Node("paris",
         layers = [n1, e4, e6, e7, e8],
         registrations = {n1 : [e4, e6, e7, e8]})

brussels = Node("brussels",
         layers = [n1, e5, e12],
         registrations = {n1 : [e5, e12]})

luxemburg = Node("luxemburg",
         layers = [n1, e7, e16],
         registrations = {n1 : [e7, e16]})

bern = Node("bern",
         layers = [n1, e8, e9, e10, e15],
         registrations = {n1 : [e8, e9, e10, e15]})

roma = Node("roma",
         layers = [n1, e10, e11, e13, e34, e28],
         registrations = {n1 : [e10, e11, e13, e34, e28]})

amsterdam = Node("amsterdam",
         layers = [n1, e12, e14, e17, e18],
         registrations = {n1 : [e12, e14, e17, e18]})

valleta = Node("valleta",
         layers = [n1, e13, e14],
         registrations = {n1 : [e13, e14]})

berlin = Node("berlin",
         layers = [n1, e15, e16, e17, e30, e31],
         registrations = {n1 : [e15, e16, e17, e30, e31]})

copenhagen = Node("copenhagen",
         layers = [n1, e18, e20, e22, e24, e19],
         registrations = {n1 : [e18, e20, e22, e24, e19]})

oslo = Node("oslo",
         layers = [n1, e20, e21],
         registrations = {n1 : [e20, e21]})

stockholm = Node("stockholm",
         layers = [n1, e21, e22],
         registrations = {n1 : [e21, e22]})

tallin = Node("tallin",
         layers = [n1, e24, e25],
         registrations = {n1 : [e24, e25]})

riga = Node("riga",
         layers = [n1, e25, e26],
         registrations = {n1 : [e25, e26]})

vilnius = Node("vilnius",
         layers = [n1, e26, e27],
         registrations = {n1 : [e26, e27]})

warsaw = Node("warsaw",
         layers = [n1, e27, e29],
         registrations = {n1 : [e27, e29]})

praha = Node("praha",
         layers = [n1, e29, e30, e32],
         registrations = {n1 : [e29, e30, e32]})

viena = Node("viena",
         layers = [n1, e32, e33, e35, e39, e28],
         registrations = {n1 : [e32, e33, e35, e39, e28]})

budapest = Node("budapest",
         layers = [n1, e33, e37, e38, e43],
         registrations = {n1 : [e33, e37, e38, e43]})

athens = Node("athens",
         layers = [n1, e39, e40, e44],
         registrations = {n1 : [e39, e40, e44]})

ljubljana = Node("ljubljana",
         layers = [n1, e35, e36],
         registrations = {n1 : [e35, e36]})

zagreb = Node("zagreb",
         layers = [n1, e36, e37],
         registrations = {n1 : [e36, e37]})

sofia = Node("sofia",
         layers = [n1, e38, e40, e42, e23],
         registrations = {n1 : [e38, e40, e42, e23]})

bucharest = Node("bucharest",
         layers = [n1, e42, e43, e41],
         registrations = {n1 : [e42, e43, e41]})

nicosia = Node("nicosia",
         layers = [n1, e44, e34],
         registrations = {n1 : [e44, e34]})

ankara = Node("ankara",
         layers = [n1, e23, e41],
         registrations = {n1 : [e23, e41]})

moscow = Node("moscow",
         layers = [n1, e31, e19],
         registrations = {n1 : [e31, e19]})

tb = jfed.Testbed(exp_name = 'geant8',
                  cert_file = '/path/to/cert.pem',
                  authority = 'wall1.ilabt.iminds.be',
                  username = 'username',
                  exp_hours = '200')

nodes = [lisbon, madrid, london, paris, dublin,
         brussels, luxemburg, bern, roma, amsterdam,
         valleta, berlin, copenhagen, oslo, stockholm,
         tallin, riga, vilnius, warsaw, praha, viena,
         budapest, athens, ljubljana, zagreb, sofia,
         bucharest, nicosia, ankara, moscow]

exp = our.Experiment(tb, nodes=nodes,
                     git_repo='https://codeberg.org/o7s/ouroboros',
                     git_branch='rand3')


with ExperimentManager(exp, swap_out_strategy=AUTO_SWAPOUT):
    exp.swap_in()
    exp.install_prototype()
    exp.bootstrap_prototype()
    for layer in layers:
        for i in range(1,4):

            duration = 1220

            sb = StoryBoard(duration + 30)

            sb.set_experiment(exp)

            for node in nodes:
                s = Server(
                    "oping",
                    options="-l",
                    arrival_rate=0.01,
                    mean_duration=duration,
                    s_id='oping_' + node.name,
                    layers=n1
                )

                sb.add_server_on_node(s, node)

            # Generate pings to check rtt, latency and drops
            couples = {(a, b) for i, a in enumerate(nodes) for b in nodes[i+1:]}

            time = 30

            for node1, node2 in couples:

                tag12 = '%s_%s' % (node1.name, node2.name)
                tag21 = '%s_%s' % (node2.name, node1.name)

                c_opt_base = "-d 940000 -i 100ms -D -n "

                client12 = Client(
                    "oping",
                    options=c_opt_base + 'oping_' + node2.name,
                    shutdown="",
                    c_id='__rpc_' + tag12
                )

                client21 = Client(
                    "oping",
                    options=c_opt_base + 'oping_' + node1.name,
                    shutdown="",
                    c_id='__rpc_' + tag21
                )

                sb.schedule_action(
                    sb.run_client,
                    args=[client12, duration, node1, '__rpp_' + tag12],
                    c_time=time,
                    ev_id='ev_run_rp_' + tag12
                )

                sb.schedule_action(
                    sb.run_client,
                    args=[client21, duration, node2, '__rpp_' + tag21],
                    c_time=time,
                    ev_id='ev_run_rp_' + tag21
                )

                time += 0.4

            sb.schedule_link_down(560, layer)
            sb.schedule_link_up(750, layer)

            prefix = layer.name + '_' + str(i)

            sb.schedule_export_lsdb_total(390, prefix + '_lsdb.csv', n1)
            sb.schedule_export_layer_bandwidth(410, prefix + '_1.csv', n1)
            sb.schedule_export_layer_bandwidth(510, prefix + '_2.csv', n1)
            sb.schedule_export_layer_bandwidth(610, prefix + '_3.csv', n1)
            sb.schedule_export_layer_bandwidth(710, prefix + '_4.csv', n1)

            sb.start()
