import sys
import os
import subprocess
import time

import mininet
import mininet.clean
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.log import lg, info
from mininet.link import TCLink, Link, TCIntf
from mininet.node import Node, OVSKernelSwitch, RemoteController
from mininet.topo import Topo
from mininet.util import waitListening,custom

import networkx as nx
import jellyfish

class JellyfishTopo( Topo ):

    def __init__(self, G):

        Topo.__init__(self)

        nx_to_mn_names = {}

        jelly_switches = [node[0] for node in list(G.nodes(data=True)) if node[1]['type'] == 'switch']
        jelly_hosts = [node[0] for node in list(G.nodes(data=True)) if node[1]['type'] == 'host']

        for switch in jelly_switches:
            mn_name = self.addSwitch(str(switch))
            nx_to_mn_names[switch] = mn_name

        for host in jelly_hosts:
            mn_name = self.addHost(str(host))
            nx_to_mn_names[host] = mn_name

        edge_list = list(G.edges())

        for edge in edge_list:
            # if edge[0] == edge[1]: # i don't think i have self loops, but maybe?
            #     continue
            self.addLink(str(nx_to_mn_names[edge[0]]), str(nx_to_mn_names[edge[1]]), cls=TCLink, bw=10, delay=10)

# topos = { 'mytopo': ( lambda: JellyfishTopo() ) }

def graph_to_topo(graph):
    """
    Builds a mininet Topology for a graph

    Parameters
    ----------
    graph : nx.Graph

    Returns
    -------
    mininet.Topo
    """

    return JellyfishTopo(graph)

def make_mininet(graph):
    """
    Constructs a mininet instance for a graph

    Parameters
    ----------
    graph : nx.Graph
        a graph generated by jellyfish.graphs

    Returns
    -------
    mininet.net.Mininet
    """
    topo = graph_to_topo(graph)

    # pox controller
    #pox = RemoteController("c1", ip="127.0.0.1", port=6633)
    pox = RemoteController("c1", ip="0.0.0.0", port=6633)

    return Mininet(topo=topo, controller=pox, link=TCLink, autoSetMacs=True)

def run(graph):
    """
    Runs the mininet CLI for a graph

    Parameters
    ----------
    graph : nx.Graph
      a graph generated by jellyfish.graphs
    """
    lg.setLogLevel('info')

    mininet.clean.cleanup()
    net = make_mininet(graph)

    net.start()
    CLI(net)
    net.stop()
