import json
import requests
import os,sys,time
from nose.tools import *
from scapy.all import *
from OnosCtrl import OnosCtrl
import fcntl, socket, struct

def get_mac(iface = 'ovsbr0', pad = 4):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', iface[:15]))
    return '0'*pad + ''.join(['%02x' %ord(char) for char in info[18:24]])

class OnosFlowCtrl:

    auth = ('karaf', 'karaf')
    controller = os.getenv('ONOS_CONTROLLER_IP') or 'localhost'
    cfg_url = 'http://%s:8181/onos/v1/flows/' %(controller)
    
    def __init__( self,
                  deviceId,
                  appId=0,
                  ingressPort="",
                  egressPort="",
                  ethType="",
                  ethSrc="",
                  ethDst="",
                  vlan="",
                  ipProto="",
                  ipSrc=(),
                  ipDst=(),
                  tcpSrc="",
                  tcpDst="",
                  udpDst="",
                  udpSrc="",
                  mpls=""):
        self.deviceId = deviceId
        self.appId = appId
        self.ingressPort = ingressPort
        self.egressPort = egressPort
        self.ethType = ethType
        self.ethSrc = ethSrc
        self.ethDst = ethDst
        self.vlan = vlan
        self.ipProto = ipProto
        self.ipSrc = ipSrc
        self.ipDst = ipDst
        self.tcpSrc = tcpSrc
        self.tcpDst = tcpDst
        self.udpDst = udpDst
        self.udpSrc = udpSrc
        self.mpls = mpls

    @classmethod
    def get_flows(cls, device_id):
        return OnosCtrl.get_flows(device_id)

    def addFlow(self):
        """
        Description:
            Creates a single flow in the specified device
        Required:
            * deviceId: id of the device
        Optional:
            * ingressPort: port ingress device
            * egressPort: port  of egress device
            * ethType: specify ethType
            * ethSrc: specify ethSrc ( i.e. src mac addr )
            * ethDst: specify ethDst ( i.e. dst mac addr )
            * ipProto: specify ip protocol
            * ipSrc: specify ip source address with mask eg. ip#/24
                as a tuple (type, ip#)
            * ipDst: specify ip destination address eg. ip#/24
                as a tuple (type, ip#)
            * tcpSrc: specify tcp source port
            * tcpDst: specify tcp destination port
        Returns:
            True for successful requests;
            False for failure/error on requests
        """
        flowJson = { "priority":100,
                     "isPermanent":"true",
                     "timeout":0,
                     "deviceId":self.deviceId,
                     "treatment":{"instructions":[]},
                     "selector": {"criteria":[]}}
        if self.appId:
            flowJson[ "appId" ] = self.appId
            
        if self.egressPort:
            flowJson[ 'treatment' ][ 'instructions' ].append( {
                    "type":"OUTPUT",
                    "port":self.egressPort } )
        if self.ingressPort:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"IN_PORT",
                    "port":self.ingressPort } )
        if self.ethType:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"ETH_TYPE",
                    "ethType":self.ethType } )
        if self.ethSrc:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"ETH_SRC",
                    "mac":self.ethSrc } )
        if self.ethDst:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"ETH_DST",
                    "mac":self.ethDst } )
        if self.vlan:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"VLAN_VID",
                    "vlanId":self.vlan } )
        if self.mpls:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"MPLS_LABEL",
                    "label":self.mpls } )
        if self.ipSrc:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":self.ipSrc[0],
                    "ip":self.ipSrc[1] } )
        if self.ipDst:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":self.ipDst[0],
                    "ip":self.ipDst[1] } )
        if self.tcpSrc:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"TCP_SRC",
                    "tcpPort": self.tcpSrc } )
        if self.tcpDst:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"TCP_DST",
                    "tcpPort": self.tcpDst } )
        if self.udpSrc:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"UDP_SRC",
                    "udpPort": self.udpSrc } )
        if self.udpDst:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"UDP_DST",
                    "udpPort": self.udpDst } )
        if self.ipProto:
            flowJson[ 'selector' ][ 'criteria' ].append( {
                    "type":"IP_PROTO",
                    "protocol": self.ipProto } )

        return self.sendFlow( deviceId=self.deviceId, flowJson=flowJson)

    def removeFlow(self, deviceId, flowId):
        """
        Description:
            Remove specific device flow
        Required:
            str deviceId - id of the device
            str flowId - id of the flow
        Return:
            Returns True if successfully deletes flows, otherwise False
        """
        # NOTE: REST url requires the intent id to be in decimal form
        query = self.cfg_url + str( deviceId ) + '/' + str( int( flowId ) )
        response = requests.delete(query, auth = self.auth)
        if response:
            if 200 <= response.status_code <= 299:
                return True
            else:
                return False

        return True

    def findFlow(self, deviceId, **criterias):
        flows = self.get_flows(deviceId)
        match_keys = criterias.keys()
        matches = len(match_keys)
        num_matched = 0
        for f in flows:
            criteria = f['selector']['criteria']
            for c in criteria:
                if c['type'] not in match_keys:
                    continue
                match_key, match_val = criterias.get(c['type'])
                val = c[match_key]
                if val == match_val:
                    num_matched += 1
                if num_matched == matches:    
                    return f['id']
        return None
                    
    def sendFlow(self, deviceId, flowJson):
        """
        Description:
            Sends a single flow to the specified device. This function exists
            so you can bypass the addFLow driver and send your own custom flow.
        Required:
            * The flow in json
            * the device id to add the flow to
        Returns:
            True for successful requests
            False for error on requests;
        """
        url = self.cfg_url + str(deviceId)
        response = requests.post(url, auth = self.auth, data = json.dumps(flowJson) )
        if response.ok:
            if response.status_code in [200, 201]:
                log.info('Successfully POSTED flow for device %s' %str(deviceId))
                return True
            else:
                log.info('Post flow for device %s failed with status %d' %(str(deviceId), 
                                                                           response.status_code))
                return False
        else:
            log.error('Flow post request returned with status %d' %response.status_code)

        return False
