import os
import socket
import re
import json
import urllib2

from mininet.log import info, warn, error
from mininet.node import Switch

if 'ONOS_ROOT' not in os.environ:
    error("ERROR: environment var $ONOS_ROOT not set")
    exit()

BMV2_TARGET = 'simple_switch_grpc'
ONOS_ROOT = os.environ["ONOS_ROOT"]
INIT_BMV2_JSON = '%s/tools/test/p4src/p4-16/p4c-out/empty.json' % ONOS_ROOT


class ONOSBmv2Switch(Switch):
    """BMv2 software switch with gRPC server"""

    deviceId = 0
    instanceCount = 0

    def __init__(self, name, debugger=False, loglevel="warn", elogger=False, persistent=False,
                 logflush=False, thriftPort=None, grpcPort=None, netcfg=True, **kwargs):
        Switch.__init__(self, name, **kwargs)
        self.thriftPort = ONOSBmv2Switch.pickUnusedPort() if not thriftPort else thriftPort
        self.grpcPort = ONOSBmv2Switch.pickUnusedPort() if not grpcPort else grpcPort
        if self.dpid:
            self.deviceId = int(self.dpid, 0 if 'x' in self.dpid else 16)
        else:
            self.deviceId = ONOSBmv2Switch.deviceId
            ONOSBmv2Switch.deviceId += 1
        self.debugger = debugger
        self.loglevel = loglevel
        self.logfile = '/tmp/bmv2-%d.log' % self.deviceId
        self.elogger = elogger
        self.persistent = persistent
        self.logflush = logflush
        self.netcfg = netcfg
        self.netcfgfile = '/tmp/bmv2-%d-netcfg.json' % self.deviceId
        if persistent:
            self.exectoken = "/tmp/bmv2-%d-exec-token" % self.deviceId
            self.cmd("touch %s" % self.exectoken)
        # Store thrift port for future uses.
        self.cmd("echo %d > /tmp/bmv2-%d-thrift-port" % (self.thriftPort, self.deviceId))
        self.cmd("echo %d > /tmp/bmv2-%d-grpc-port" % (self.grpcPort, self.deviceId))

    @classmethod
    def pickUnusedPort(cls):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('localhost', 0))
        addr, port = s.getsockname()
        s.close()
        return port

    def getSourceIp(self, dstIP):
        """
        Queries the Linux routing table to get the source IP that can talk with dstIP, and vice
        versa.
        """
        ipRouteOut = self.cmd('ip route get %s' % dstIP)
        r = re.search(r"src (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", ipRouteOut)
        return r.group(1) if r else None

    def doOnosNetcfg(self, controllerIP):
        """
        Notifies ONOS about the new device via Netcfg.
        """
        srcIP = self.getSourceIp(controllerIP)
        if not srcIP:
            warn("WARN: unable to get device IP address, won't do onos-netcfg")
            return
        onosDeviceId = "bmv2:%s" % self.deviceId
        cfgData = {
            "devices": {
                "device:%s" % onosDeviceId: {
                    "generalprovider": {
                        "p4runtime": {
                            "ip": srcIP,
                            "port": self.grpcPort,
                            "deviceKeyId": "p4runtime:%s" % onosDeviceId
                        }
                    },
                    "basic": {
                        "driver": "bmv2"
                    }
                }
            }
        }
        with open(self.netcfgfile, 'w') as fp:
            json.dump(cfgData, fp, indent=4)
        # Build netcfg URL
        url = 'http://%s:8181/onos/v1/network/configuration/' % controllerIP
        # Instantiate password manager for HTTP auth
        pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
        pm.add_password(None, url, os.environ['ONOS_WEB_USER'], os.environ['ONOS_WEB_PASS'])
        urllib2.install_opener(urllib2.build_opener(urllib2.HTTPBasicAuthHandler(pm)))
        # Push config data to controller
        req = urllib2.Request(url, json.dumps(cfgData), {'Content-Type': 'application/json'})
        try:
            f = urllib2.urlopen(req)
            print f.read()
            f.close()
        except urllib2.URLError as e:
            warn("WARN: unable to push config to ONOS (%s)" % e.reason)

    def start(self, controllers):
        args = [BMV2_TARGET, '--device-id %s' % str(self.deviceId)]
        for port, intf in self.intfs.items():
            if not intf.IP():
                args.append('-i %d@%s' % (port, intf.name))
        if self.thriftPort:
            args.append('--thrift-port %d' % self.thriftPort)
        if self.elogger:
            nanomsg = 'ipc:///tmp/bmv2-%d-log.ipc' % self.deviceId
            args.append('--nanolog %s' % nanomsg)
        if self.debugger:
            args.append('--debugger')
        args.append('--log-file %s -L%s' % (self.logfile, self.loglevel))
        if self.logflush:
            args.append('--log-flush')

        args.append(INIT_BMV2_JSON)

        # gRPC target-specific options.
        args.append('--')
        args.append('--enable-swap')
        args.append('--grpc-server-addr 0.0.0.0:%d' % self.grpcPort)

        bmv2cmd = " ".join(args)
        info("\nStarting BMv2 target: %s\n" % bmv2cmd)
        if self.persistent:
            # Bash loop to re-exec the switch if it crashes.
            cmdStr = "(while [ -e {} ]; " \
                     "do {} ; " \
                     "sleep 1; " \
                     "done;) &".format(self.exectoken, bmv2cmd)
        else:
            cmdStr = "{} &".format(bmv2cmd)

        # Starts the switch.
        out = self.cmd(cmdStr)
        if out:
            print out

        if self.netcfg:
            try:  # onos.py
                clist = controllers[0].nodes()
            except AttributeError:
                clist = controllers
            assert len(clist) > 0
            cip = clist[0].IP()
            self.doOnosNetcfg(cip)

    def stop(self, deleteIntfs=True):
        """Terminate switch."""
        self.cmd("rm -f /tmp/bmv2-%d-*" % self.deviceId)
        # wildcard end as BMv2 might create log files with .txt extension
        self.cmd("rm -f /tmp/bmv2-%d.log*" % self.deviceId)
        self.cmd('kill %' + BMV2_TARGET)
        Switch.stop(self, deleteIntfs)


# Exports for bin/mn
switches = {'onosbmv2': ONOSBmv2Switch}
